3

我们目前正在设计一个解决方案,它将作为 WebSeal 反向代理后面的 .Net Web 应用程序运行。

我在网上看到一些评论,人们对此有各种问题,例如重写视图状态。

问题是:有没有人实施了这种技术组合并让它发挥作用?

4

2 回答 2

8

我在 WEBSEAL 后面制作了一个 ASP.NET 应用程序。经过大量的研究和开发和测试,它可以工作。

我建议一些问题来帮助你:

IIS 和 ASP.NET 不区分大小写

(“...Login.aspx”和“...login.aspx”都指向同一个页面);默认情况下,webseal 区分大小写。因此,您应该将 WEBSEAL 连接设置为不区分大小写或检查任何单个链接(页面、javascript、图像)

不会提供以服务器相对 URL形式编写的内部链接

WEBSEAL 会更改引用您的应用程序的任何链接,但不会更改指向其他应用程序的链接。写入为服务器相对 URL而不是应用程序相对 URL的内部链接不会被更改(WEBSEAL 无法识别它是同一个应用程序)并且不会被提供(WEBSEAL 拒绝未修改的链接)。
第一条规则是检查任何单个链接并将其设为应用程序相对 URL
如果您发现,请查看呈现的 HTML <.. href=/ anything>:this ia server relative URL,它很糟糕。如果您使用它是好的,
请查看后面的代码。"= ~/ anything"如果你使用 "= / anything"ORResolveUrl(..)那就不好了。

但这还不够:AJAX 将大量 javascript 和代码放入ScriptResource.axdWebResource.axd中,并创建服务器相对 URL 来链接它。此链接不受程序员控制,也没有简单的方法可以更改它们。
简单的解决方案(如果可能):解决将 WEBSEAL junction 设置为透明的问题。
硬解:编写以下代码(感谢this answer

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表单以编程方式读取它。现在,为了使这个用户成为 CurrentUser,我放置了一个隐藏的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是 FormsAuthentication 类将重定向到的登录页面的 URL。它已设置为 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">

就是这样!

于 2011-09-07T11:54:52.770 回答
2

当通过 WebSeal 访问 ASP.Net 应用程序时,我最初遇到了一些问题。我在开发服务器上运行该站点。对我有用的是在配置文件中关闭调试来部署应用程序。

<compilation debug="false" ...>

打开调试后,有一些 AJAX 调用在我直接访问该站点时可以正常工作,但在通过 WebSeal 访问时会失败。关闭调试后,一切正常。

此外,由于 WebSeal 需要匿名身份验证,我们不能使用 Windows 身份验证。

于 2010-12-21T21:15:38.060 回答