Веб-приложение.Net за обратным прокси-сервером WebSeal
В настоящее время мы разрабатываем решение, которое будет работать как веб-приложение.Net за обратным прокси-сервером WebSeal.
Я видел некоторые комментарии в сети, где у людей были различные проблемы с этим, например, переписывание viewstate.
Вопрос: кто-нибудь реализовал эту комбинацию технологий и заставил ее работать?
2 ответа
У меня изначально есть некоторые проблемы с приложением ASP.Net при доступе через WebSeal. Я запускал сайт на сервере разработки. Для меня работало развертывание приложения с отключенной отладкой в файле конфигурации.
<compilation debug="false" ...>
При включенной отладке были некоторые вызовы AJAX, которые работали бы нормально, когда я обращался к сайту напрямую, но не могли работать при доступе через WebSeal. Как только я выключил отладку, все работает нормально.
Кроме того, поскольку WebSeal требует анонимной аутентификации, мы не могли использовать аутентификацию Windows.
Я сделал приложение ASP.NET работающим за WEBSEAL. После большого количества изучения и развития и тестирования это работает.
Я предлагаю несколько вопросов, чтобы помочь вам:
IIS и ASP.NET нечувствительны к регистру
("...Login.aspx" и "...login.aspx" ведут на одну и ту же страницу); по умолчанию webseal чувствителен к регистру. Поэтому вы должны установить соединение WEBSEAL без учета регистра или проверить любую отдельную ссылку (страницу, javascript, изображение)
Внутренние ссылки, написанные как относительные URL сервера, не будут обслуживаться
WEBSEAL изменяет любую ссылку, относящуюся к вашему приложению, но не меняет ссылки на другие приложения. Внутренние ссылки, записанные как относительные URL сервера, а не относительные URL приложения, не будут изменены (WEBSEAL не распознает, что это то же самое приложение) и не будут обслуживаться (WEBSEAL отклоняет ссылки, которые не были изменены).
Первое правило - проверить любую отдельную ссылку и сделать ее относительной ссылкой приложения.
Посмотрите на визуализированный HTML, если найдете <.. href=/ anything>
Это относительный URL сервера, и это плохо.
Посмотрите в коде позади, если вы используете "= ~/ anything"
это хорошо. Если вы используете "= / anything"
ИЛИ ЖЕ ResolveUrl(..)
это плохо.
Но этого недостаточно: AJAX помещает множество javascript и кода в ScriptResource.axd и WebResource.axd и создает относительный URL-адрес сервера, чтобы связать его. Эти ссылки не контролируются программистами, и нет простого способа их изменить.
Простое решение (если возможно): решите проблему, установив соединение WEBSEAL прозрачным.
Трудное решение: напишите следующий код (благодаря этому ответу)
protected void Page_Load(object sender, EventArgs e)
{
//Initialises my dirty hack to remove the leading slash from all web reference files.
Response.Filter = new WebResourceResponseFilter(Response.Filter);
}
public class WebResourceResponseFilter : Stream
{
private Stream baseStream;
public WebResourceResponseFilter(Stream responseStream)
{
if (responseStream == null)
throw new ArgumentNullException("ResponseStream");
baseStream = responseStream;
}
public override bool CanRead
{ get { return baseStream.CanRead; } }
public override bool CanSeek
{ get { return baseStream.CanSeek; } }
public override bool CanWrite
{ get { return baseStream.CanWrite; } }
public override void Flush()
{ baseStream.Flush(); }
public override long Length
{ get { return baseStream.Length; } }
public override long Position
{
get { return baseStream.Position; }
set { baseStream.Position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{ return baseStream.Read(buffer, offset, count); }
public override long Seek(long offset, System.IO.SeekOrigin origin)
{ return baseStream.Seek(offset, origin); }
public override void SetLength(long value)
{ baseStream.SetLength(value); }
public override void Write(byte[] buffer, int offset, int count)
{
//Get text from response stream.
string originalText = System.Text.Encoding.UTF8.GetString(buffer, offset, count);
//Alter the text.
originalText = originalText.Replace(HttpContext.Current.Request.ApplicationPath + "/WebResource.axd",
VirtualPathUtility.MakeRelative(HttpContext.Current.Request.Url.AbsolutePath, "~/WebResource.axd"));
originalText = originalText.Replace(HttpContext.Current.Request.ApplicationPath + "/ScriptResource.axd",
VirtualPathUtility.MakeRelative(HttpContext.Current.Request.Url.AbsolutePath, "~/ScriptResource.axd"));
//Write the altered text to the response stream.
buffer = System.Text.Encoding.UTF8.GetBytes(originalText);
this.baseStream.Write(buffer, 0, buffer.Length);
}
Это перехватывает поток на страницу и заменяет все вхождения "/WebResource.axd" или "ScriptResource.axd" на "../../WebResource.axd" и "../../ScriptResource.axd"
Разработайте код для получения реального пользователя WEBSEAL
WEBSEAL был настроен для помещения имени пользователя в HTTP_IV_USER. Я создал форму Webseal\Login.aspx, чтобы читать ее программно. Теперь, чтобы сделать этого пользователя текущим пользователем, я поставил скрытый asp.Login
<span style="visibility:hidden">
<asp:Login ID="Login1" runat="server" DestinationPageUrl="~/Default.aspx">..
и нажал кнопку программно
protected void Page_Load(object sender, EventArgs e)
{
string username = Request.ServerVariables["HTTP_IV_USER"];
(Login1.FindControl("Password") as TextBox).Text = MyCustomProvider.PswJump;
if (!string.IsNullOrEmpty(username))
{
(Login1.FindControl("UserName") as TextBox).Text = username;
Button btn = Login1.FindControl("LoginButton") as Button;
((IPostBackEventHandler)btn).RaisePostBackEvent(null);
}
else
{
lblError.Text = "Login error.";
}
}
Когда срабатывает LoginButton, приложение считывает имя пользователя (установлено из переменной WEBSEAL) и пароль (жестко запрограммировано). Поэтому я реализовал пользовательский поставщик членства, который проверяет пользователей и устанавливает текущий Принципал.
Изменения в web.config
loginUrl - это URL-адрес страницы входа, на которую будет перенаправлен класс FormsAuthentication. Он был установлен на портале WEBSEAL: не прошедший проверку пользователь и кнопка выхода будут перенаправлены на портал.
<authentication mode="Forms">
<forms loginUrl="https://my.webseal.portal/" defaultUrl="default.aspx"...."/>
</authentication>
Поскольку Webseal/login.aspx НЕ является страницей входа по умолчанию, тег авторизации предоставляет доступ не прошедшим проверку пользователям:
<location path="Webseal/login.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
Приложение настроено на использование пользовательских провайдеров членства:
<membership defaultProvider="MyCustomMembershipProvider">
<providers>
<add name="MyCustomMembershipProvider" type="MyNamespace.MyCustomMembershipProvider" connectionStringName="LocalSqlServer"/>
</providers>
</membership>
<roleManager enabled="true" defaultProvider="MyCustomRoleProvider">
<providers>
<add name="MyCustomRoleProvider" type="MyNamespace.MyCustomRoleProvider" connectionStringName="LocalSqlServer"/>
</providers>
</roleManager>
Отладка отключена:
<compilation debug="false" targetFramework="4.0">