这是我的Global.asax.cs
文件:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
...
}
protected void Application_Start()
{
this.PostAuthenticateRequest += new EventHandler(MvcApplication_PostAuthenticateRequest);
}
// This method never called by requests...
protected void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new GenericPrincipal(identity, new string[] { });
Context.User = principal;
}
}
}
PostAuthenticateRequest
何时执行?
答案 0 :(得分:20)
安全模块具有时发生 确立了用户的身份。
...
PostAuthenticateRequest事件是 在AuthenticateRequest之后提出 事件已经发生。功能性 订阅了 PostAuthenticateRequest事件可以 访问由...处理的任何数据 PostAuthenticateRequest。
但是因为您的问题是用ASP.NET MVC标记的,所以我强烈建议您将其执行到自定义[Authorize]
属性而不是使用此事件。例如:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (isAuthorized)
{
var authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new GenericPrincipal(identity, new string[] { });
httpContext.User = principal;
}
}
return isAuthorized;
}
}
现在使用[MyAuthorize]
属性装饰您的控制器/操作:
[MyAuthorize]
public ActionResult Foo()
{
// if you got here the User property will be the custom
// principal you injected in the authorize attribute
...
}
答案 1 :(得分:9)
如果您将代码放在PostAuthenticateRequest上,则每个请求可能会多次命中,因为页面上引用的图像和样式表等每个资源都会触发此事件,因为它们被视为单独的请求。
如果你使用@ Darin的答案,当isAuthorized返回false时,AuthorizeAttribute将不会呈现操作,但是人们可能无论如何都需要呈现它,即使它是一个公共页面(不受限制的访问)你可能想要显示“显示名称”保存在authTicket的userData部分。
为此,我建议在ActionFilterAttribute(AuthenticationFilter)上加载authCookie:
public class LoadCustomAuthTicket : ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
if (!filterContext.Principal.Identity.IsAuthenticated)
return;
HttpCookie authCookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null)
return;
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new GenericPrincipal(identity, new string[] { });
// Make sure the Principal's are in sync. see: https://www.hanselman.com/blog/SystemThreadingThreadCurrentPrincipalVsSystemWebHttpContextCurrentUserOrWhyFormsAuthenticationCanBeSubtle.aspx
filterContext.Principal = filterContext.HttpContext.User = System.Threading.Thread.CurrentPrincipal = principal;
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
//This method is responsible for validating the current principal and permitting the execution of the current action/request.
//Here you should validate if the current principle is valid / permitted to invoke the current action. (However I would place this logic to an authorization filter)
//filterContext.Result = new RedirectToRouteResult("CustomErrorPage",null);
}
}
在global.asax.cs上
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LoadCustomAuthTicket());
}
这样您也不必使用属性填充所有操作。