1

我正在研究使用 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 标头后无法重定向。

说明:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

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

源错误:

在执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪来识别有关异常起源和位置的信息。

堆栈跟踪:

[HttpException (0x80004005): HTTP headers 发送后无法重定向。] System.Web.HttpResponse.Redirect(String url, Boolean endResponse) +8712587
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.RedirectToIdentityProvider(String uniqueId, String returnUrl, Boolean persist ) +249
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.OnEndRequest(Object sender, EventArgs args) +438
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +68 System.Web.HttpApplication.ExecuteStep(IExecutionStep 步骤, 布尔值和完成同步)+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似乎没有触发。

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

4

2 回答 2

1

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

    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 的授权来控制哪些用户可以访问每个页面。

于 2011-11-02T08:28:09.277 回答
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

于 2011-11-09T22:28:17.813 回答