WebSeal 反向代理背后的 .Net Web 应用程序

发布于 2024-09-24 06:32:58 字数 138 浏览 6 评论 0原文

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

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

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

We are currently designing a solution that will run as a .Net Web application behind a WebSeal reverse proxy.

I have seen some comments on the net where people have had various problems with this, for example rewriting of viewstate.

Question is: Has anyone implemented this combination of techologies and got it to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不寐倦长更 2024-10-01 06:32:58

我在 WEBSEAL 后面创建了一个 ASP.NET 应用程序。经过大量的研究、开发和测试,它是有效的。

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

IIS 和 ASP.NET 不区分大小写

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

内部链接,写为服务器相对 URL > 不会提供服务

WEBSEAL 更改引用您的应用程序的任何链接,但不会更改到其他应用程序的链接。
写为服务器相对 URL 而不是应用程序相对 URL 的内部链接不会更改(WEBSEAL 无法识别它是同一个应用程序)并且不会提供服务( WEBSEAL 拒绝未修改的链接)。
第一条规则是检查任何单个链接并将其设为应用程序相对 URL
查看渲染的 HTML,如果您发现 <.. href=/ everything> :此 ia 服务器相对 URL 并且它是错误的。
查看隐藏代码,如果使用 "= ~/ everything" 就很好了。如果您使用 "= / everything"ResolveUrl(..) 那就不好了。

但这还不够:AJAX 将大量 JavaScript 和代码放入 ScriptResource.axdWebResource.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 表单以编程方式读取它。
现在,为了使该用户成为 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 触发时,应用程序读取 UserName(从 WEBSEAL 变量设置)并密码(硬编码)。所以我实现了自定义会员资格提供程序验证用户并设置当前主体。

web.config 中的更改

loginUrl是 FormsAuthentication 类将重定向到的登录页面的 URL。它已设置为 WEBSEAL 门户:未经身份验证的用户和注销按钮将重定向到门户。

<authentication mode="Forms">
  <forms loginUrl="https://my.webseal.portal/" defaultUrl="default.aspx"...."/>
</authentication>

由于Webseal/login.aspx不是默认登录页面,authorization 标签向未经过身份验证的用户授予访问权限:

<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">

就是这样!

I made an ASP.NET application workin behind WEBSEAL. After lot of study and development and test it works.

I suggest some issues to help you:

IIS and ASP.NET are case insensitive

("...Login.aspx" and "...login.aspx" both lead to the same page); by default webseal is case sensitive. So you should set WEBSEAL junction to be case insensitive or check any single link (page, javascript, image)

Internal links, written as server relative URLs won't be served

WEBSEAL changes any link referring your application but doesn't change links to other applications.
Internal links, written as server relative URLs instead of application relative URLs won't be changed (WEBSEAL doesn't recognize it's the same application) and won't be served (WEBSEAL rejects links that are not modified).
First rule is to check any single link and make it an application relative URL .
Look at rendered HTML if you find <.. href=/ anything> : this i a server relative URL and it is bad.
Look in the Code Behind if you use "= ~/ anything" it is good. If you use "= / anything" OR ResolveUrl(..) it is bad.

But this is not enough: AJAX puts loads of javascript and code inside ScriptResource.axd and WebResource.axd and creates server relative URL to link it. This links are not controlled by programmers and there is no easy way to change them.
Easy solution (if possible): solve the problem setting WEBSEAL junction to be transparent.
Hard solution: write the following code (thanks to 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);

    }

This intercepts the stream to the page and replaces all occurrences of "/WebResource.axd" or "ScriptResource.axd" with "../../WebResource.axd" and "../../ScriptResource.axd"

Develop code to get actual WEBSEAL user

WEBSEAL has been configured to put username inside HTTP_IV_USER. I created Webseal\Login.aspx form to read it programmatically.
Now, in order to make this user the CurrentUser I put an hidden asp.Login

<span style="visibility:hidden"> 
<asp:Login ID="Login1" runat="server" DestinationPageUrl="~/Default.aspx">..

and clicked the button programmatically

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.";
    }
}

When LoginButton fires, application reads UserName (set from WEBSEAL variable) and password (hard coded). So i implemented a custom membership provider that validates users and sets current Principal.

Changes in web.config

loginUrl is the URL for the login page that the FormsAuthentication class will redirect to. It has been set to WEBSEAL portal: not authenticated user and logout button will redirect to portal.

<authentication mode="Forms">
  <forms loginUrl="https://my.webseal.portal/" defaultUrl="default.aspx"...."/>
</authentication>

Since Webseal/login.aspx is NOT default login page, authorization tag grants access to not authenticated users:

<location path="Webseal/login.aspx">
    <system.web>
        <authorization>
            <allow users="*"/>
        </authorization>
    </system.web>
</location>

Application is set to use custom membership providers:

 <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>

Debug is set to off:

<compilation debug="false" targetFramework="4.0">

that's all folks!

秋风の叶未落 2024-10-01 06:32:58

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

<compilation debug="false" ...>

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

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

I initially has some issues with the ASP.Net app when accessed through WebSeal. I was running the site on a development server. What worked for me was to deploy the application with debugging turned off in the config file.

<compilation debug="false" ...>

With debugging turned on, there were some AJAX calls that would work fine when I accessed the site directly but would fail when access through WebSeal. Once I turned the debugging off, everything work fine.

Also, because WebSeal requires anonymous authentication, we couldn't have used Windows Authentication.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文