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 MVC5+EF6+EasyUI 后台管理系统(65)-MVC WebApi 用户验证 (1)
系列目录 前言: WebAPI主要开放数据给手机APP,其他需要得知数据的系统,或者软件应用,所以移动端与系统的数据源往往是相通的. Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能, ...
- asp.net mvc 自定义全局过滤器 验证用户是否登录
一般具有用户模块的系统都需要对用户是否登录进行验证,如果用户登录了就可以继续操作,否则退回用户的登录页面 对于这样的需求我们可以通过自定义一个独立的方法来完成验证的操作,但是这样代码的重复率就大大提高 ...
- SSM框架笔记14:Spring MVC表单验证
Spring MVC表单验证 在Spring MVC中,表单验证有三种方法. 一.基本校验 这种方法是基于handler的,优点是定义方便,缺点是不便于复用. 1.两个接口:Errors/Bi ...
- ASP.NET MVC 2 模型验证
2019独角兽企业重金招聘Python工程师标准>>> [原文地址]ASP.NET MVC 2: Model Validation [原文发表日期] Friday, January ...
- JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践
任何时候,当要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情. 应用程序必须通过某种手段来确保输入参数在上下文来说是正确的. 分层的应用在很多时候,同样的数据验证逻辑会出现在不同的层, ...
- mvc html validator,ASP.NET MVC实现Validation验证器扩展
今天介绍在ASP.NET MVC实现Validation验证器扩展,通过使用Controller验证并不是最好的方法:验证过于分散,容易造成重复代码,不利于维护与扩展,因此本节将使用MVC默认绑定器( ...
- Spring MVC表单验证(带批注)
这篇文章提供了一个简单HTML表单验证示例. 它基于带有注释的Spring MVC示例. 该代码可在GitHub的Spring-MVC-Form-Validation目录中找到. 数据 在此示例中,我 ...
- mongodb 系列 ~ mongo 用户验证系列
MongoClientURI connectionString = new MongoClientURI("mongodb://root:****@dds-bp114e3f1fc441342 ...
- java 异常返回json_Spring MVC全局异常后返回JSON异常数据
问题: 当前项目是作为手机APP后台支持,使用spring mvc + mybaits + shiro进行开发.后台服务与手机端交互是发送JSON数据.如果后台发生异常,会直接返回异常页面,显示异常内 ...
最新文章
- (康托展开解释)+ NYOJ 139 我排第几个
- Spring Cloud Config采用数据库存储配置内容
- Policy Injection Application Block
- C++构造函数和文件组织
- 在 SAP HANA database Explorer 里添加 HDI 容器
- 历史数据如何处理_数据库表数据量大读写缓慢如何优化(1)【冷热分离】
- 分布式流媒体直播服务器系统 For Linux
- 网页设计上机考试原题_全国计算机三级信息安全考试 经验分享
- 推理 —— 猜帽子颜色
- 第四季-专题5-内核模块开发
- atan和atan2反正切计算
- 图扑软件数字孪生 | 基于 BIM 技术的可视化管理系统
- 【视频】CCNA——小凡模拟器的简单介绍和使用
- 【特效】UE4 Niagara 制作爆炸特效
- 使用MACD指标在上证指数000001.SH上开发单边多头策略
- JDBC 加载驱动报错解决办法
- Microsoft Store转圈圈
- 【嵌入式蓝桥杯】解决LED和LCD引脚冲突的方法
- UUID和UUID_SHORT
- 2021年三季度中国家居用品行业A股上市企业营收排行榜:欧派家居、顾家家居排名前2位,且近五年第三季度的净利润均逐年递增(附热榜TOP61详单)
热门文章
- 标准 C++ I/O
- C++11之异步调用
- 玩转Numpy——np.ravel()的使用
- oracle 存储怎么使用,Oracle存储过程中如何使用数组(附范例)
- Numpy中的堆叠(stack)操作
- SQL Server查询所有数据库下模式schema
- Java中什么是字符串的拷贝_关于java中字符串对象的拷贝
- python小屋_Python小屋——Python语言基础(三)
- Qt学习笔记之SQLITE数据库
- MFC中简单绘图几种方式