我正在研究使用WIF识别在EPiServer上运行的客户站点的部件上的用户的可能性。我设法让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> </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
的覆盖似乎没有触发。
这里有什么可能错误的提示?
答案 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。