前言

很多时候其实我们并不需要asp.net core自带的那么复杂的用户系统,基于角色,各种概念,还得用EF Core,而且在web应用中都是把信息存储到cookie中进行通讯(我不喜欢放cookie中,因为有次我在mac系统中的safari浏览器运行web应用时,碰到跨域cookie设不上,非要使用个很特殊的方法,记得是iframe,挺麻烦的,所以我还是喜欢放自定义header中), 用了以后感觉被微软给绑架了。不过这完全是个人喜好,大家完全可以按自己喜欢的来,我这里提供了另外一条路,大家可以多一种选择。

我这边是利用asp.net core的依赖注入,定义了一套属于自己系统的用户认证与授权,大家可以参考我这个来定义自己的,也不局限于用户系统。

面向切面编程(AOP)

在我看来,Middleware与Filter都是asp.net core中的切面,我们可以把认证与授权放到这两块地方。我个人比较喜欢把认证放到Middleware,可以提早把那些不合法的攻击拦截返回。

依赖注入(DI)

依赖注入有3种生命周期

1. 在同一个请求发起到结束。(services.AddScoped)

2. 每次注入的时候都是新建。(services.AddTransient)

3. 单例,应用开始到应用结束。(services.AddSingleton)

我的自定义用户类采用的是services.AddScoped。

具体做法

1. 定义用户类

1     //用户类,随便写的
2     public classMyUser3 {4         public string Token { get; set; }5         public string UserName { get; set; }6     }

2. 注册用户类

Startup.cs中的ConfigureServices函数:

1         //This method gets called by the runtime. Use this method to add services to the container.
2         public voidConfigureServices(IServiceCollection services)3 {4 ...5             //注册自定义用户类
6             services.AddScoped(typeof(MyUser));7 ...8         }

自定义用户类,是通过services.AddScoped方式进行注册的,因为我希望它在同一个请求中,Middleware, filter, controller引用到的是同一个对象。

3. 注入到Middleware

1     //You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
2     public classAuthenticationMiddleware3 {4         private readonlyRequestDelegate _next;5         private IOptions<HeaderConfig>_optionsAccessor;6
7         public AuthenticationMiddleware(RequestDelegate next, IOptions<HeaderConfig>optionsAccessor)8 {9             _next =next;10             _optionsAccessor =optionsAccessor;11 }12
13         public asyncTask Invoke(HttpContext httpContext, MyUser user)14 {15             var token =httpContext.Request.Headers[_optionsAccessor.Value.AuthHeader].FirstOrDefault();16             if (!IsValidate(token))17 {18                 httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;19                 httpContext.Response.ContentType = "text/plain";20                 await httpContext.Response.WriteAsync("UnAuthentication");21 }22             else
23 {24                 //设置用户的token
25                 user.Token =token;26                 await_next(httpContext);27 }28 }29
30         //随便写的,大家可以加入些加密,解密的来判断合法性,大家自由发挥
31         private bool IsValidate(stringtoken)32 {33             return !string.IsNullOrEmpty(token);34 }35 }36
37     //Extension method used to add the middleware to the HTTP request pipeline.
38     public static classAuthenticationMiddlewareExtensions39 {40         public static IApplicationBuilder UseAuthenticationMiddleware(thisIApplicationBuilder builder)41 {42             return builder.UseMiddleware<AuthenticationMiddleware>();43 }44     }

我发现如果要把接口/类以Scoped方式注入到Middleware中,就需要把要注入的类/接口放到Invoke函数的参数中,而不是Middleware的构造函数中,我猜这也是为什么Middleware没有继承基类或者接口,在基类或者接口中定义好Invoke的原因,如果它在基类或者接口中定义好Invoke,势必这个Invoke的参数要固定死,就不好依赖注入了。

4. 配置某些路径才会使用该Middleware

1         //This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
2         public voidConfigure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)3 {4             loggerFactory.AddConsole(Configuration.GetSection("Logging"));5 loggerFactory.AddDebug();6             //Set up nlog
7 loggerFactory.AddNLog();8 app.AddNLogWeb();9
10             //除了特殊路径外,都需要加上认证的Middleware
11             app.MapWhen(context => !context.Request.Path.StartsWithSegments("/api/token")12                                  && !context.Request.Path.StartsWithSegments("/swagger"), x =>
13 {14                 //使用自定义的Middleware
15 x.UseAuthenticationMiddleware();16                 //使用通用的Middleware
17 ConfigCommonMiddleware(x);18 });19             //使用通用的Middleware
20 ConfigCommonMiddleware(app);21
22             //Enable middleware to serve generated Swagger as a JSON endpoint.
23 app.UseSwagger();24
25             //Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
26             app.UseSwaggerUI(c =>
27 {28                 c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");29 });30 }31
32         //配置通用的Middleware
33         private voidConfigCommonMiddleware(IApplicationBuilder app)34 {35             //cors
36             app.UseCors("AllowAll");37
38 app.UseExceptionMiddleware();39             //app.UseLogRequestMiddleware();
40 app.UseMvc();41         }

像获取token啊,查看api文档啊就不需要认证了。

5. 注入到Filter

1     public classNeedAuthAttribute : ActionFilterAttribute2 {3private string _name = string.Empty;4privateMyUser _user;5
6         public NeedAuthAttribute(MyUser user, string name = "")7 {8             _name =name;9             _user =user;10 }11
12         public override voidOnActionExecuting(ActionExecutingContext context)13 {14             this._user.UserName = "aaa";15 }16     }

这里我创建的是个带字符串参数的类,因为考虑到这个Filter有可能会被复用,比如限制某个接口只能被某种用户访问, 这个字符串便可以存某种用户的标识。

Filter中还可以注入数据库访问的类,这样我们便可以到数据库中通过token来获取到相应的用户信息。

6. 使用Filter

1 [TypeFilter(typeof(NeedAuthAttribute), Arguments = new object[]{ "bbb" }, Order = 1)]2 public class ValuesController : Controller

这里使用了TypeFilter,以加载使用了依赖注入的Filter, 并可以设置参数,跟Filter的顺序。

默认Filter的顺序是 全局设置->Controller->Action, Order默认都为0,我们可以通过设置Order来改变这个顺序。

7. 注入到Controller

1     public classValuesController : Controller2 {3         privateMyUser _user;4
5         publicValuesController(MyUser user)6 {7             _user =user;8 }9 ...10     }

注入到Controller的构造函数中,这样我们就可以在Controller的Action中使用我们自定义的用户,就能知道到底当前是哪个用户在调用这个Action。

转载于:https://www.cnblogs.com/nickppa/p/6903694.html

asp.net core利用DI实现自定义用户系统,脱离ControllerBase.User相关推荐

  1. asp.net core系列 47 Identity 自定义用户数据

    一.概述 接着上篇的WebAppIdentityDemo项目,将自定义用户数据添加到Identity DB,自定义扩展的用户数据类应继承IdentityUser类, 文件名为Areas / Ident ...

  2. ASP.NET Core奇遇记:无用户访问,CPU却一直100%

    这是5月11日遇到的一个问题,1台1核1G阿里云Linux服务器运行着生产环境中的ASP.NET Core站点,出现CPU 100%问题. 开始以为是这台服务器负载高引起的,于是将这台服务器从负载均衡 ...

  3. ASP.NET中实现复用代码自定义用户控件UserControl的使用

    场景 ASP.NET中新建Web网站并部署到IIS上(详细图文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/107199 ...

  4. 用Scrutor来简化ASP.NET Core的DI注册

    目录 背景 Scrutor简介 Scrutor的简单使用 注册接口的实现类 注册类自身 重复注册处理策略 总结 相关文章 背景 在我们编写ASP.NET Core代码的时候,总是离不开依赖注入这东西. ...

  5. ASP.NET Core 集成测试中模拟登录用户的一种姿势

    不管哪种用户验证方式,最终都是在验证成功后设置 HttpContext.User ,后续处理环节通过 HttpContext.User 获取用户信息.如果能直接修改 HttpContext.User ...

  6. [翻译] ASP.NET Core 利用 Docker、ElasticSearch、Kibana 来记录日志

    一步一步指导您使用 ElasticSearch, Kibana, ASP.NET Core 2.1 和 Docker 来记录日志 在本教程中,我将向您展示如何启动和运行 ElasticSearch,K ...

  7. 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统

    2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为"希赛网" ...

  8. ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页

    关键字:DataGrid.存储过程.分页 出自: http://blog.csdn.net/yzx110/archive/2004/08/18/78525.aspx 摘要:在最进的一个项目中因为一个管 ...

  9. ASP.NET Core利用拦截器 IActionFilter实现权限控制

    "麦荻网教系统"采用了前后端代码分离的架构,即"Miidy.Cloud.Console"站与"Miidy.Cloud.Manage"站(两个 ...

最新文章

  1. UVA 1354 Mobile Computing
  2. HTML 5 中的新元素2
  3. [Silverlight入门系列]使用MVVM模式(6):使用Behavior
  4. Luogu P3731 [HAOI2017]新型城市化
  5. LeetCode#53 Maximum Subarray
  6. Android学习笔记(27):日历视图Calendar
  7. java根据sessionid获取session
  8. OJ和PTA常见的错误代码含义
  9. 修改 decimal 默认值为0.00 sql_书写高性能SQL语句技巧,网友都说好
  10. java oracle的2种分页方法
  11. Fiddler 4——手机抓包工具
  12. Himawari8注册后发来信息下载数据
  13. java 判断客户端是手机端还是PC端(SSH框架)
  14. 下行法求最小割集案例_无向图求最小割集
  15. python sl4a_SL4A - 随风飘落的雨滴 - 博客园
  16. evernote 有道_如何备份Evernote笔记本(以防万一)
  17. 2018今日头条内推笔试1
  18. Vue3项目运行时报错,提示Use // eslint-disable-next-line to ignore the next line.
  19. 微服系列之Feign使用HttpClient和OkHttp网络请求框架
  20. 电子信息类与计算机类专业,电子信息类与计算机类有什么不同?就业方向呢

热门文章

  1. [资源]181个Python开源项目分享!
  2. 门禁系统服务器 控制器 读卡器,你知道门禁系统读卡器分为多少种吗?
  3. java注解 interface_java @FunctionalInterface注解详解
  4. iou画 yolov3_yolov3环境配置训练及优化
  5. python网络编程知识点_python 网络编程要点
  6. Java从string数组创建临时文件
  7. PHP闭包(Closure)初探(转载 http://my.oschina.net/melonol/blog/126694?p=2#comments)
  8. (剑指Offer)面试题5:从尾到头打印链表
  9. UVA10763:Foreign ExchangeUVA10340: All in All(水题)
  10. 通用滤波器设计----东南大学的