您好,欢迎访问一九零五行业门户网

asp.net core使用DI实现自定义用户系统

前言很多时候其实我们并不需要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 myuser3     {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             else23             {24                 // 设置用户的token25                 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 authenticationmiddlewareextensions39     {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             // 除了特殊路径外,都需要加上认证的middleware11             app.mapwhen(context => !context.request.path.startswithsegments(/api/token)12                                  && !context.request.path.startswithsegments(/swagger), x =>13             {14                 // 使用自定义的middleware15                 x.useauthenticationmiddleware();16                 // 使用通用的middleware17                 configcommonmiddleware(x);18             });19             // 使用通用的middleware20             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         // 配置通用的middleware33         private void configcommonmiddleware(iapplicationbuilder app)34         {35             // cors36             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。
以上就是asp.net core使用di实现自定义用户系统的详细内容。
其它类似信息

推荐信息