【问题标题】:EPiServer and Windows Identity Foundation (WIF)EPiServer 和 Windows 身份基础 (WIF)
【发布时间】:2011-11-01 07:55:13
【问题描述】:

我正在研究使用 WIF 在 EPiServer 上运行的客户站点的部分上识别用户的可能性。我已经设法让 WIF 开始使用以下帖子:

http://world.episerver.com/Blogs/Ben-Morris/Dates/2010/6/Converting-EPiServer-6-to-use-claims-based-authentication-with-WIF/

如果你设置了这个效果很好

<authorization>
    <deny users="?"/>
</authorization>

在 web.config 中,发出所有请求都需要经过身份验证的用户。但是,我们想使用 EPiServer 来区分哪些内容应该可供匿名用户和经过身份验证的用户使用。问题是,我就是无法让它工作。

当我启用 WIF 并且不设置 deny users="*" 时,EPiServer 会在启用 WIF 以执行重定向之前启动并向响应流输出一些文本:

HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Tue, 01 Nov 2011 07:51:04 GMT
Connection: close

Access denied.

</pre></table></table></table></table></table></font></font></font></font></font></i></i></i></i></i></b></b></b></b></b></u></u></u></u></u><p>&nbsp;</p><hr>

当 WIF 尝试重定向到 STS 时,这会导致以下错误:

“/”应用程序中的服务器错误。

发送 HTTP 标头后无法重定向。

描述:执行过程中发生了未处理的异常 当前的网络请求。请查看堆栈跟踪以获取更多信息 有关错误的信息以及它在代码中的来源。

异常详细信息:System.Web.HttpException:之后无法重定向 HTTP 标头已发送。

来源错误:

在执行过程中产生了一个未处理的异常 当前的网络请求。有关原产地和位置的信息 可以使用下面的异常堆栈跟踪来识别异常。

堆栈跟踪:

[HttpException (0x80004005): HTTP headers 后无法重定向 已发送。] System.Web.HttpResponse.Redirect(String url, Boolean endResponse) +8712587
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.RedirectToIdentityProvider(字符串 uniqueId,字符串 returnUrl,布尔值持久化)+249
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.OnEndRequest(对象 发件人,EventArgs 参数)+438
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +68 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

我已经搜索了高和低,以便能够覆盖此行为。在 EPiServer.dll 中,我发现以下地方输出的文本与输出内容相似:

AccessDeniedDelegateHandler.cs,方法BrowserLogonAccessDenied(object sender)

internal static void BrowserLogonAccessDenied(object sender)
{
  HttpContext.Current.Response.Clear();
  HttpContext.Current.Response.Status = "401 Unauthorized";
  HttpContext.Current.Response.Write("Access denied.");
  HttpContext.Current.Response.Flush();
  HttpContext.Current.Response.End();
}

据我所知,这段代码是从以下两个地方调用的:

  • EPiServer.Global,方法protected virtual void HandleAccessDenied()
  • EPiServer.PageBase,方法public virtual void AccessDenied()

我试图在Global.asax 中覆盖HandleAccessDenied,并在我的页面模板中覆盖AccessDenied。但是,仍会输出“拒绝访问”文本。看起来好像我的页面模板中的 AcccessDenied 覆盖正在触发,但是,HandleAccessDenied 的覆盖似乎没有触发。

关于这里可能出现什么问题的任何提示?

【问题讨论】:

    标签: episerver wif episerver-6


    【解决方案1】:

    发现问题。我尝试覆盖PageBaseAccessDenied 方法,但是,我犯了与默认实现相同的“错误”,即刷新响应流:

        public override void AccessDenied()
        {
            Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            Response.Flush(); // <- This was the problem
            Response.End();
            // The rest is handled by WIF when we send a HTTP 401, think nothing more of it..
        }
    

    解决方案是简单地避免刷新响应流。然后 WIF 处理剩下的事情:

        public override void AccessDenied()
        {
            Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            // Removed the flushing of the response
            Response.End();
            // The rest is handled by WIF when we send a HTTP 401, think nothing more of it..
        }
    

    这允许我们使用 EPI 的授权来控制哪些用户可以访问每个页面。

    【讨论】:

      【解决方案2】:

      您可以添加一个特殊的登录表单(因为您仍然依赖表单身份验证)来实际触发登录,而不是覆盖 AccessDenied 行为。

      public class FederatedLoginHandler : IHttpHandler, IRequiresSessionState
      {
          public void ProcessRequest(HttpContext context)
          {
              if (context.User.Identity.IsAuthenticated)
              {
                  FormsAuthentication.RedirectFromLoginPage(context.User.Identity.Name, false);
              }
              else
              {
                  context.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
              }
          }
      }
      

      在 web.config 中设置处理程序

      <system.webServer>
        <handlers>
          <!--"Fake" login handler, simply triggers WIF auth-->
          <add name="LoginForm" path="federatedlogin.ashx" verb="GET,HEAD" type="SomeAssembly.FederatedLoginHandler" />
          ...
      

      最后设置身份验证以使用新的处理程序

      <authentication mode="Forms">
        <forms name=".LoginPage" loginUrl="federatedlogin.ashx" timeout="120" />
      </authentication>
      

      此策略不需要修改 EPiServer、WIF 或标准 ASP.Net 行为。当然,您需要基本的 WIF 配置才能使其工作http://msdn.microsoft.com/en-us/library/gg638734.aspx

      【讨论】:

      • 我不依赖表单身份验证,但也许这是个好主意。但是,我必须重写 EPiServer 功能的唯一原因是,如果您不使用表单身份验证,它们会刷新响应流。我认为正确的解决方法是让 EPiServer 内置功能不刷新响应流。然后 WIF 将开箱即用......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      • 1970-01-01
      • 2011-02-12
      相关资源
      最近更新 更多