1

我正在使用 HttpModule 重写多语言网站上的网址。在 HttpModule 中,我为 BeginRequest 事件添加了一个处理程序,并寻找包含文化名称的路径的第一部分。

例如,/fr-ca/index.aspx 将被重写为 /index.aspx 并将线程的文化和 ui 文化设置为 3084。这工作正常。

输入表单身份验证。表单身份验证仍然适用于未映射的 url,但如果用户未经授权,它将重定向到 web.config 的身份验证部分中设置的 loginUrl,并包含 ?ReturnUrl= 查询字符串参数以处理重定向回请求的用户通过身份验证后的页面。

如果用户请求使用非默认语言的页面,这里有两个问题:

  1. loginUrl 在重写之前忽略路径
  2. ReturnUrl 参数也忽略了原始路径。

它等效于 Request.Url.PathAndQuery 而不是 Request.RawUrl。

我不能在 AuthorizeRequest 事件中跳入管道,因为那时我必须防止所有可能的文化值,因为我正在使用一个具有多个位置路径的 web.config 文件。这也不能解决第一个问题。

我已经浏览了反射器中的 FormsAuthenticationModule,我看到了可以在哪里更改它以解决 #1 和 #2,但它当然是密封的。

我也浏览了很多,但我看不到任何可行的解决方案。

FormsAuthenticationModule 正在检查 UrlAuthorizationModule 中生成的 401 标头。如果您在 loginUrl 页面上查找引荐来源网址(为空),它会确认这一点。

有什么想法吗?

编辑#1

我正在使用 IIS 6,而 IIS 7 不是一个选项。

编辑#2

登录页面没有选择默认的文化/用户界面文化,因为当我生成本地资源(设计视图:工具 > 生成本地资源)时,IDE 将以下内容添加到页面指令中:

文化=“自动”元:资源键=“页面资源1”uiculture=“汽车”

在 vs.net 2008 中注意这一点!至少这解决了未引用默认文化的问题之一,但 #1 和 #2 仍然很突出。

编辑 3

我希望我可以跳入其中一个管道事件来进行自己的重定向,但是在反映 System.Web.Security.UrlAuthorizationModule OnEnter 方法中,我了解到一旦设置了 401 标头,该方法就会调用 application.CompleteRequest,它正如您所猜到的,将我们带到 EndRequest 事件。这就是FA模块跳进做重定向的东西,我怕跳到前面做自己的重定向!我很惊讶没有更多的人遇到这个问题,或者他们可能还没有加入。


例子:

我在受表单身份验证保护的物理文件夹 /members/ 中有一个成员部分。

在 web.config 中,我有:

<authentication mode="Forms">
  <forms loginUrl="~/members/login.aspx" timeout="40" />
</authentication>

和...

  <location path="members">
      <system.web>
          <authorization>
              <deny users="?" />
              <allow roles="Members" />
              <deny users="*" />
          </authorization>
      </system.web>
  </location>

当未经身份验证的用户请求 /members/ 的索引页面时,他们会被 FormsAuthenticationModule 从上面的身份验证部分重定向到 loginUrl。它还将 ?ReturnUrl 参数附加到请求的页面。

如果用户使用默认文化浏览网站,这很好用,但我的 HttpModule 根据路径第一部分中存在的文化名称设置文化。

因此,/fr-ca/members/index.aspx 被重写为 /members/index.aspx 并将文化/ui 文化设置为加拿大法语。不幸的是,FormsAuthenticationModule 使用重写的 url 将用户发送到 loginUrl 页面,而不是原来的。因此,文化设置丢失并且重定向 url 不正确。

希望对@Greg有帮助

4

2 回答 2

3

好的,问题解决了。

原来关键是清除 machine.config httpModules,添加我的自定义 httpModule,然后添加回所需的默认 httpModules。这允许我的自定义 httpModule 在 FormsAuthenticationHttpModule 之前跳转到 EndRequest 事件。

<httpModules>
    <clear/>
    <!-- custom -->
    <add name="LocalizationHttpModule" type="LocalizationHttpModule"/>
    <!-- add back defaults, exlude PassportAuthentication, AnonymousIdentification, Profile -->
    <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
    <add name="Session" type="System.Web.SessionState.SessionStateModule" />
    <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
    <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
    <add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
    <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
    <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />

</httpModules> 

然后,在我的自定义 httpModule 中,我只需点击 EndRequest,查找 401 状态代码,然后按照我的意愿进行重定向。基本上我正在重写 FormsAuthenticationHttpModule OnLeave 方法的代码以满足我的需要。

Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init

    Dim authentication As AuthenticationSection = WebConfigurationManager.GetSection("system.web/authentication")
    If authentication.Mode = AuthenticationMode.Forms Then
        Me._LoginUrl = authentication.Forms.LoginUrl
        AddHandler context.EndRequest, AddressOf Context_EndRequest
    End If

End Sub

Private Sub Context_EndRequest(ByVal sender As Object, ByVal e As EventArgs)
    Dim application As HttpApplication = DirectCast(sender, HttpApplication)
    Dim context As HttpContext = application.Context

    If (context.Response.StatusCode = &H191) Then                
       ' do custom redirect here
    End If

End Sub
于 2009-08-01T17:35:25.690 回答
1

我能想到的唯一一件事就是手动重定向到登录表单。

1) 允许所有访问会员目录
2) 会员中的所有页面直接继承自 Page 的子类。
3) 在 Page 子类的 PreInit(?) 中,检查用户是否是成员角色的成员。
4)如果没有,请自己构建登录页面的URL,包括ReturnURL参数并将用户重定向到您的登录URL。

您也可以通过在 web.config 中放置一堆 <location> 部分来破解此问题。例如:< location path="fr-ca/members">< authenication>< forms loginUrl="~/fr-ca/members/login.aspx">...但我真的不知道。

可能还有其他我不熟悉的方法。

于 2009-07-31T19:04:10.057 回答