MVC全局用户验证之HttpModule
在请求进入到MVC的处理mcvHandler之前,请求先到达HttpModule,因此可以利用HttpModule做全局的用户验证。
HttpModule
MVC5之前的版本基于system.web.dll库,MvcApplication继承自HttpApplication,以Http管道的方式运行,HttpApplication是整个ASP.NET基础架构的核心,HttpApplication处理请求的整个生命周期是一个相对复杂的过程,在该过程的不同阶段会触发相应的事件
| 名称 | 描述 |
| BeginRequest | HTTP管道开始处理请求时,会触发BeginRequest事件 |
| AuthenticateRequest,PostAuthenticateRequest | ASP.NET先后触发这两个事件,使安全模块对请求进行身份验证 |
| AuthorizeRequest,PostAuthorizeRequest | ASP.NET先后触发这两个事件,使安全模块对请求进程授权 |
| ResolveRequestCache,PostResolveRequestCache | ASP.NET先后触发这两个事件,以使缓存模块利用缓存的直接对请求直接进程响应(缓存模块可以将响应内容进程缓存,对于后续的请求,直接将缓存的内容返回,从而提高响应能力)。 |
| PostMapRequestHandler | 对于访问不同的资源类型,ASP.NET具有不同的HttpHandler对其进程处理。对于每个请求,ASP.NET会通过扩展名选择匹配相应的HttpHandler类型,成功匹配后,该实现被触发 |
| AcquireRequestState,PostAcquireRequestState | ASP.NET先后触发这两个事件,使状态管理模块获取基于当前请求相应的状态,比如SessionState |
| PreRequestHandlerExecute,PostRequestHandlerExecute | ASP.NET最终通过一请求资源类型相对应的HttpHandler实现对请求的处理,在实行HttpHandler前后,这两个实现被先后触发 |
| ReleaseRequestState,PostReleaseRequestState | ASP.NET先后触发这两个事件,使状态管理模块释放基于当前请求相应的状态 |
| UpdateRequestCache,PostUpdateRequestCache | ASP.NET先后触发这两个事件,以使缓存模块将HttpHandler处理请求得到的相应保存到输出缓存中 |
| LogRequest,PostLogRequest | ASP.NET先后触发这两个事件为当前请求进程日志记录 |
| EndRequest | 整个请求处理完成后,EndRequest事件被触发 |
HttpApplication提供了基于事件的扩展机制,允许程序员借助于处理管道中的事件进行处理过程扩展。在Asp.net中,提供了两种方式来解决这个问题:IHttpModule方式和golbal.asax方式。这两种方式的核心都是IHttpModule接口。
从功能上讲,HttpModule之于ASP.NET,就好比ISAPI Filter之于IIS一样。IIS将接收到的请求分发给相应的ISAPI Extension之前,注册的ISAPI Filter会先截获该请求。
当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于HTTP请求来讲,HttpModule是一个HTTP请求的“必经之路”,所以可以在这个HTTP请求传递到真正的请求处理中心(HttpHandler)之前附加一些需要的信息在这个HTTP请求信息之上,或者针对截获的这个HTTP请求信息作一些额外的工作,或者在某些情况下干脆终止满足一些条件的HTTP请求,从而可以起到一个Filter过滤器的作用。
public class BasicAuthenticationHttpModule : IHttpModule{private static IAuthenticationService _authenticationService;public static void SetBasicAuthenticationValidator(IAuthenticationService authenticationService){_authenticationService = authenticationService;}public void Init(HttpApplication context){//核心:用户认证事件处理context.PostAuthenticateRequest += ContextOnAuthenticateRequest;}private static void ContextOnAuthenticateRequest(object sender, EventArgs eventArgs){if (_authenticationService == null ||HttpContext.Current == null ||HttpContext.Current.User == null ||HttpContext.Current.User.Identity.IsAuthenticated)return;try{IPrincipal principal = null;var headers = HttpContext.Current.Request.Headers;var authValue = headers[HttpRequestHeader.Authorization.ToString()];//if no Basic header, don't prompt for itif (authValue == null ||string.IsNullOrWhiteSpace(authValue) ||!authValue.StartsWith("Basic")){return;}//try to parse for itvar parsedCredentials = ParseAuthorizationHeader(authValue);if (parsedCredentials != null){principal = _authenticationService.ValidateCredentials(parsedCredentials.Item1, parsedCredentials.Item2);}if (principal == null){Unauthorized(HttpContext.Current);return;}SetPrincipal(principal);}catch (SecurityException){throw;}catch (Exception ex){throw new SecurityException("Unexpected error. See inner exception for details.", ex);}}private static void Unauthorized(HttpContext context){Trace.TraceWarning("Unauthorized basic credentials");context.Response.Headers.Add("WWW-Authenticate", "Basic");context.Response.StatusCode = 401;context.Response.StatusDescription = "Invalid credentials";context.ApplicationInstance.CompleteRequest();}private static Tuple<string, string> ParseAuthorizationHeader(string authHeader){try{string base64Credentials = authHeader.Substring(6);var credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(new[] { ':' });if (credentials.Length != 2 ||string.IsNullOrEmpty(credentials[0]) ||string.IsNullOrEmpty(credentials[1])){return null;}return new Tuple<string, string>(credentials[0], credentials[1]);}catch (Exception exception){Trace.TraceError("BasicAuthentication: ParseHeader " + exception);throw;}}private static void SetPrincipal(IPrincipal principal){Thread.CurrentPrincipal = principal;HttpContext.Current.User = Thread.CurrentPrincipal;}public void Dispose(){}}
进行注册
<system.webServer><modules><add name="BasicAuthenticationHttpModule" type="WebApplication1.BasicAuthenticationHttpModule" /></modules> </system.webServer>Global.asaxvoid Application_Start(object sender, EventArgs e) {BasicAuthenticationHttpModule.SetBasicAuthenticationValidator(new AuthenticationService()); }总结
以上是生活随笔为你收集整理的MVC全局用户验证之HttpModule的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: ASP.NET的MVC请求处理流程
- 下一篇: MVC5管道处理模型