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

前言

很多时候其实我们并不需要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 class MyUser
3     {
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 void ConfigureServices(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 class AuthenticationMiddleware
 3     {
 4         private readonly RequestDelegate _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 async Task 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(string token)
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 class AuthenticationMiddlewareExtensions
39     {
40         public static IApplicationBuilder UseAuthenticationMiddleware(this IApplicationBuilder 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 void Configure(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 void ConfigCommonMiddleware(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 class NeedAuthAttribute : ActionFilterAttribute
 2     {
 3         private string _name = string.Empty;
 4         private MyUser _user;
 5 
 6         public NeedAuthAttribute(MyUser user, string name = "")
 7         {
 8             _name = name;
 9             _user = user;
10         }
11 
12         public override void OnActionExecuting(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 class ValuesController : Controller
 2     {
 3         private MyUser _user;
 4 
 5         public ValuesController(MyUser user)
 6         {
 7             _user = user;
 8         }
 9         ...
10     }

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

 

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html的排版标题的是,HTML 5结构排版布局

进行总体布局时候&#xff0c;具体可以用的方法。1.大纲&#xff1a;文档中各内容区块的结构编排。内容区块可以使用标题元素来展示各级内容区块的标题。关于内容区块的编排可以分为“显示编排”和“隐式编排”。显示编排&#xff1a;明确使用section等元素创建文档结构&#x…

[LeetCode]Distinct Subsequences,解题报告

题目 Given a string S and a string T, count the number of distinct subsequences of T in S.A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative po…

2021年河南高考成绩排名查询一分一段表,2018河南高考一分一段统计表,查排名必备!...

原标题&#xff1a;2018河南高考一分一段统计表&#xff0c;查排名必备&#xff01;&#xff1a;点击这里信息省招办公布了2018年普通高招分数段统计表&#xff0c;对每个分数段有多少考生进行了详细统计。你考了多少分&#xff1f;处在哪个位置&#xff1f;快来看看&#xff0…

实用的css样式

当字数超过一行时&#xff0c;可以用...代替 white-space: nowrap; overflow: hidden; text-overflow: ellipsis; 这三个样式同时使用才有效&#xff0c;也可以去掉white-space样式&#xff0c;分两行 转载于:https://www.cnblogs.com/maggie-php/p/6906462.html

js滚轮换切屏

js滚轮换切屏 因为全项目不是自己写的&#xff0c;仅仅是帮别人写js滚轮代码&#xff0c;并且别人项目也还未上线。所以仅仅贴出自己写的那段部分代码&#xff0c; 效果&#xff1a;鼠标滚轮滚动时。网頁屏幕一屏一屏的上下切换 (下面代码在本地电脑的IE,chrome与FireFox这三个…

(2021|CoRR,AugCLIP,优化)FuseDream:通过改进的 CLIP+GAN 空间优化实现免训练文本到图像生成

FuseDream: Training-Free Text-to-Image Generation with Improved CLIPGAN Space Optimization 公众&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 2. CLIPGAN 文本到图…

中文邮件营销html模版,怎么制作邮件营销模板?— —邮件格式

怎么制作邮件营销模板&#xff1f;— —邮件格式U-Mail邮件营销平台发表时间 2017-09-21人气 757次做EDM邮件营销&#xff0c;需要有好的邮件群发工具&#xff0c;还要有好的内容&#xff0c;那么如何制作好邮件营销的模板呢&#xff1f;现在U-Mail邮件群发平台根据已有的一些经…

查询数据库中所有表名

查询数据库中所有表名select table_name from information_schema.tables where table_schemacsdb and table_typebase table; 查询指定数据库中指定表的所有字段名column_nameselect column_name from information_schema.columns where table_schemacsdb and table_nameusers…

【默认加入持久化机制,防止消息丢失,v0.0.3】对RabbitMQ.Client进行一下小小的包装,绝对实用方便...

RabbitMQ是一个老牌的非微软的消息队列组件&#xff0c;一般来说应该能满足中小型公司对消息队列生产的需求&#xff0c;平时我们在.NET开发环境下运用它是可能会需要RabbitMQ.Client的SDK库&#xff0c;此库是官网提供&#xff0c;目前最新发布版本是v4.1.3。在我们对接项目时…

angularJS中,怎么阻止事件冒泡

今天有个童鞋问我&#xff0c;ng怎么阻止事件冒泡&#xff0c;我就简单的贴一下代码吧&#xff0c;也不是什么好高大上的问题 转载于:https://www.cnblogs.com/leoshuaige/p/6910646.html

用html编写输出今天是星期几,利用Date对象编写程序,判断并输出今天是开学的第几周,星期几。...

利用Date对象编写程序&#xff0c;判断并输出今天是开学的第几周&#xff0c;星期几。(function(){var startDay new Date(2014,8,1); //根据指定的年月日时分秒设置开学时间为2014/09/01var startMs startDay.getTime();//返回1970年至今的毫秒var startYear startD…

Java中 break continue return 的区别

1、break break :跳出当前循环&#xff1b;但是如果是嵌套循环&#xff0c;则只能跳出当前的这一层循环&#xff0c;只有逐层break才能跳出所有循环&#xff1b; for (int i 0; i < 10; i) { if (i 6) { break; // 在执行i6时强制终止循环&#xff0c;i6不会被执行 }Sy…

用计算机画好看的图形,如何画一手漂亮的电脑效果图?技巧案例赏析!

原标题&#xff1a;如何画一手漂亮的电脑效果图&#xff1f;技巧&案例赏析&#xff01;电脑效果图是什么&#xff1f;很显然&#xff0c;用电脑去绘制设计师的想法。当然&#xff01;所有的设计意图&#xff0c;最终都是为了更准确的成衣。那么&#xff0c;能精准的表达出想…

朝花夕拾——finally/final/finalize拨云雾见青天

Java编程中。常常会使用到异常处理&#xff0c;而finally看似的是try/catch后对逻辑处理的完好&#xff0c;事实上里面却存在非常多隐晦的陷阱。final常见于变量修饰&#xff0c;那么你在内部类中也见过吧。finalize作为GC回收对象前的一道门&#xff0c;什么时候运行。运行效果…

Java读源代码学设计模式:适配器Adapter

适配器模式相关源代码&#xff1a;slf4j-1.6.1、hibernate-3.6.7大家都知道。log4j是一个广泛使用的日志工具&#xff0c;除此之外。sun公司在JDK中也有自己的日志工具&#xff0c;也就是java.util.logging.Logger。当然还有其它一些日志工具。多种日志工具功能和使用方式相似&…

适合文科女孩子学的计算机类专业,文科女生最吃香的专业2021 哪些专业有前景...

文科女生最吃香的专业2021 哪些专业有前景2021-03-27 14:36:27文/丁雪竹文科女生可以报考的专业并不是很多&#xff0c;小编整理了文科女生吃香的专业&#xff0c;来看一下&#xff01;文科女生最吃香的专业网络与新媒体这个专业是近几年流行起来的新兴专业&#xff0c;需求量还…

系统搭建遇到问题3:Ubuntu问题造成网卡名称异常导致Vivado绑定网卡地址的Lic无法正常工作(JESD)...

解决方法参考&#xff1a; ubuntu平台vivado无法识别NIC_ID而无法使用license的解决办法 http://blog.csdn.net/cirs_q/article/details/60574030转载于:https://www.cnblogs.com/abolide/p/6920397.html

中职计算机基础知识总结,中职计算机基础知识整理

中职计算机基础知识整理计算机基础知识(初稿2011/10/5)1、计算机发展简史第一代(1946-1957年)电子管第二代(1958-1964年)晶体管第三代(1964-1970年)中、小规模集成电路第四代(1971年至今)大规模和超大规模集成电路2、我国计算机发展我国电子计算机研究工作起步于1956年1958年试…

多个html如何套用套一个头部,Vue.js项目中管理每个页面的头部标签的两种方法...

在 Vue SPA 应用中&#xff0c;如果想要修改 HTML 的头部标签&#xff0c;如页面的 title &#xff0c;我们只能去修改 index.html 模板文件&#xff0c;但是这个是全局的修改&#xff0c;如何为每个页面都设置不一样的 title 呢&#xff1f;下面介绍两种方法。使用router.Meta…

Ubuntu16.04下Mongodb官网安装部署步骤(图文详解)(博主推荐)

不多说&#xff0c;直接上干货&#xff01; 在这篇博客里&#xff0c;我采用了非官网的安装步骤&#xff0c;来进行安装。走了弯路&#xff0c;同时&#xff0c;也是不建议。因为在大数据领域和实际生产里&#xff0c;还是要走正规的为好。 Ubuntu16.04下Mongodb&#xff08;离…