循序渐进学.Net Core Web Api开发系列【15】:应用安全

循序渐进学.Net Core Web Api开发系列【15】:应用安全,第1张

概述原文: 循序渐进学.Net Core Web Api开发系列【15】:应用安全 系列目录 循序渐进学.Net Core Web Api开发系列目录  本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi   一、概述 本篇介绍Web系统的应用安全,主要涉及用户的身份认证和访问权限问题。 大部分web应用习惯采用Session来保存用户认证信 @H_419_1@ 原文: 循序渐进学.Net Core Web Api开发系列【15】:应用安全

系列目录

循序渐进学.Net Core Web Api开发系列目录

 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi

 

一、概述

本篇介绍Web系统的应用安全,主要涉及用户的身份认证和访问权限问题。

大部分web应用习惯采用Session来保存用户认证信息,对于WebAPI而言,调用者不一定是Web浏览器,可能是AndroID、iOS客户端,可能是微信小程序,也可能是客户端程序等等,这些客户端模拟构造cookie、存储或传递sessionID都不是太方便,这种情况下,采用令牌(tockenID)的方式进行授权管理就显得比较方便,唯一不方便的就是每次调用都要传递tockenID。

基本流程如下:

1、调用登陆接口,通过正确的用户名和密码活动TockenID;

2、通过TockenID调用其他业务接口。

 

二、基本使用

1、处理用户登陆的Controller

        [httpPost("login")]        public ResultObject Login(string loginname,string password)        {            try            {                User user = _context.Users                    .AsNoTracking()                    .Where(a => a.Loginname == loginname && a.Password == password)                    .Single();                String tockenID = Tocken.GetTockenID();                _cache.Set(tockenID,user,new MemoryCacheEntryOptions().SetSlIDingExpiration(TimeSpan.FromSeconds(20)));                return new ResultObject                {                    state = ResultState.Success,result = tockenID                };            }            catch(InvalIDOperationException ex)            {                return new ResultObject                {                    state = ResultState.Exception,ExceptionString = "未找到匹配的数据"                };            }                   }

首先在数据库寻找匹配的用户信息,如果验证成功就以TockenID为主键把用户信息存入缓存,并设置过期时间(示例代码中过期时间为20秒),然后返回TockenID。

 

2、在业务Controller中根据传入TockenID的进行用户认证。

[httpGet]        public ResultObject GetAllArticles(string tockenID)        {            User user = null;           if(!_cache.TryGetValue(tockenID,out user))            {                return new ResultObject                {                    state = ResultState.Fail,ExceptionString = "请登陆"                };            }            List<Article> articles = _context.Articles                    .AsNoTracking()                    .ToList<Article>();            return new ResultObject            {                state = ResultState.Success,result = articles            };        }

 

三、采用中间件进行用户认证

因为每个业务Controller都需要进行认证,所以按上述方法就比较麻烦了,我们做个中间件来进行统一身份验证

namespace SaleService.System.MIDdleware{    public class UserAuthenticationMIDdleware    {        private Readonly RequestDelegate _next;        private Readonly ILogger _logger;        private Readonly IMemoryCache _cache;        public UserAuthenticationMIDdleware(RequestDelegate next,ILogger<UserAuthenticationMIDdleware> logger,IMemoryCache memoryCache)        {            _next = next;            _logger = logger;            _cache = memoryCache;        }        public async Task Invoke(httpContext context)        { 
//如果是登陆接口就不需要验证Tocken if (context.Request.Path.ToString().Tolower().StartsWith("/API/user/login")) { await _next(context); return; } if (context.Request.Path.ToString().Tolower().StartsWith("/API/")) { string tockenID = context.Request.query["tockenID"]; if (tockenID == null) { var result = new ResultObject { state = ResultState.Exception,ExceptionString = "Need tockenID" }; context.Response.ContentType = "application/Json; charset=utf-8"; context.Response.WriteAsync(JsonConvert.SerializeObject(result)); return; } User user = null; if (!_cache.TryGetValue(tockenID,out user)) { context.Response.StatusCode = 401; context.Response.ContentType = "application/Json; charset=utf-8"; context.Response.WriteAsync("InvalIDate tockenID(用户认证失败)"); return; } } await _next(context); } } public static class UserAuthenticationMIDdlewareExtensions { public static IApplicationBuilder UseUserAuthentication(this IApplicationBuilder builder) { return builder.UseMIDdleware<UserAuthenticationMIDdleware>(); } }}

该中间件直接截取Request中的tockID进行验证,如果验证不通过就直接返回“短路”其他中间件,所以在使用时需要放在MVC中间件前面。

public class Startup    {
// This method gets called by the runtime. Use this method to configure the http request pipeline. public voID Configure(IApplicationBuilder app,IHostingEnvironment env,ILoggerFactory loggerFactory) { app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyheader().AllowCredentials()); app.UseStaticfiles(); app.UseUserAuthentication();//要放在UseMvc前面 app.UseMvcWithDefaultRoute(); } }

 此时业务Controller就比较简单干净了,专心做业务就可以了

      [httpGet]        public ResultObject GetAllArticles(string tockenID)        {                List<Article> articles = _context.Articles                    .AsNoTracking()                    .ToList<Article>();                      return new ResultObject            {                state = ResultState.Success,result = articles            };        }      

此时,如果需要,仍可以通过tockenID获取用户信息。

 

四、关于访问的权限

此时用户需要登陆才能访问受限业务API,但对用户权限并没有约束,实际应用时需要建立角色,通过用户于角色对应关系和角色与资源的对应关系,确认用户可以访问的资源列表。

 

五、几点需要优化的地方

这里描述了通过TockenID进行用户认证的基本思路,实际应用时还有很多需要改善的地方:

1、对于一些公开应用是不需要验证的,如果在中间件中通过if来判断路径就显得比较丑陋,是否可以通过给这些Controller加上相关的特性来进行标识?

2、如何方便地判断用户与资源的对应关系?

3、Controller中通过tockenID获取用户信息的方法能否封装一下?

这些问题暂时还没有考虑充分,以后有机会完善一下。

总结

以上是内存溢出为你收集整理的循序渐进学.Net Core Web Api开发系列【15】:应用安全全部内容,希望文章能够帮你解决循序渐进学.Net Core Web Api开发系列【15】:应用安全所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1230164.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存