EPiServer和Windows Identity Foundation(WIF)

时间:2011-11-01 07:55:13

标签: episerver wif episerver-6

我正在研究使用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标头出现后无法重定向   已发送。] System.Web.HttpResponse.Redirect(String url,Boolean   endResponse)+8712587
  Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.RedirectToIdentityProvider(字符串   uniqueId,String returnUrl,Boolean persist)+249
  Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.OnEndRequest(对象   发件人,EventArgs args)+438
  System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()   +68 System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean&amp; 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()

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

这里有什么可能错误的提示?

2 个答案:

答案 0 :(得分:1)

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

PageBase

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

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

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

答案 1 :(得分:0)

您可以添加特殊的登录表单(因为您仍然依赖表单身份验证)来实际触发登录,而不是覆盖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