2011-11-01 44 views
1

我正在研究使用WIF识别在EPiServer上运行的客户站点的部件上的用户的可能性。我已经成功地得到WIF使用,除其他外,以下后踢:EPiServer和Windows Identity Foundation(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:

Server Error in '/' Application.

Cannot redirect after HTTP headers have been sent.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: Cannot redirect after HTTP headers have been sent.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[HttpException (0x80004005): Cannot redirect after HTTP headers have been sent.] 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 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()

我试图覆盖HandleAccessDeniedGlobal.asax,并在我的页面模板中覆盖AccessDenied。但是,仍然输出“访问被拒绝”文本。它好像在我的页面模板中覆盖AcccessDenied正在触发,但HandleAccessDenied的覆盖似乎并未触发。

任何提示可能是错误的地方?

回答

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

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

+0

我不是依靠Forms身份验证,但也许这是一个好主意。但是,我必须重写EPiServer功能的唯一原因是,如果您不使用窗体身份验证,它们会刷新响应流。我认为正确的修复方法是EPiServer内置功能不会刷新响应流。然后WIF可以开箱即用...... –

相关问题