欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET Core的JWT的实现(中间件).md

程序员文章站 2022-04-16 14:41:10
既然选择了远方,便只顾风雨兼程 __ HANS许 JWT(JSON Web Token) ASP.NET Core 的Middleware实现 引言:挺久没更新了,之前做了Vue的系列,后面想做做服务端的系列,上下衔接,我们就讲讲WebApi(网络应用程序接口),接口免不了用户认证,所以接下来我们的 ......

既然选择了远方,便只顾风雨兼程 __ hans许

 

 

引言:挺久没更新了,之前做了vue的系列,后面想做做服务端的系列,上下衔接,我们就讲讲webapi(网络应用程序接口),接口免不了用户认证,所以接下来我们的主题系列文章便是“基于asp.net core的用户认证”,分为市面上流行的jwt(json webtoken)与oauth2(开放授权)

jwt(json web token)

  • 什么叫jwt
    json web token(jwt)是目前最流行的跨域身份验证解决方案。

    一般来说,互联网用户认证是这样子的。

    1、用户向服务器发送用户名和密码。
    2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
    3、服务器向用户返回一个 session_id,写入用户的 cookie。
    4、用户随后的每一次请求,都会通过 cookie,将 session_id 传回服务器。
    5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

    服务器需要保存session,做持久化,这种模式没有分布式架构,无法支持横向扩展,如果真的要的话就必须采用分布式缓存来进行管理seesion。那jwt相反,它保存的是在客户端,每次请求都将jwt代入服务器,进行签名,权限验证。jwt由客户端请求,服务端生成,客户端保存,服务端验证。

  • jwt的原理与格式

    1. 原理
      在上面,我们也讲过了,简单的来说,我们将服务器需要验证我们的条件(账户,密码等等),发给服务器,服务器认证通过,生成一个json对象返回给我们,例如下面。当然,为了防止被篡改,所以我们会将对象加密,再次请求服务器,需要将jwt放在请求头部,传递给服务器,来判断权限等等。

      1. "姓名": "张三"
      2. "角色": "管理员"
      3. "到期时间": "2018年7月1日0点0分" 
    2. 格式

      • 实际格式
      1. eyjhbgcioijiuzi1niisinr5cci6ikpxvcj9. 
      2. eyjbijoiqufbqsisikiioijcqkjciiwiqyi6ikndq0milcj1zxiioij4dwh1ywxliiwib3blbmlkijointe1njezmtm1mtyzmjeilcjmzii6imrmc2rzzgzzzgzzzhmilcjuymyioje1ntiymte4njasimv4cci6mtu1mjixmzy2mh0. 
      3. 16m57ynnicgith25dwphqkpyuiq42bvmzv6libo7kdg 

      它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,jwt内部是没有换行的,这里只是为了便于展示,将它写成了几行。jwt 的三个部分依次如下。

      • header(头部)
      • payload(负载)
      • signature(签名)

      简单讲下,header描述加密算法与token类型,payload描述的是实际需要传递的数据,如失效时间,签发人等等,signature描述的是一段对于前面两部部分的签名,当然秘钥只有服务器才知道。

简单的介绍下jwt,更多的话,可以这边看看。我们着重讲下实现。

asp.net core 的middleware实现
  1. 创建jwt
    首先我们要先创建token,毕竟这个是最重要的。core自带jwt帮助类,所以我们按照帮助类的意思来写个方法创建token。

    1. public string createjsonwebtoken(dictionary<string, string> payload) 
    2. if (string.isnullorwhitespace(setting.securitykey)) 
    3. throw new argumentnullexception("jsonwebtokensetting.securitykey"
    4. "securitykey为null或空字符串。请在\"appsettings.json\"配置\"jsonwebtoken\"节点及其子节点\"securitykey\""); 
    5. var now = datetime.utcnow; 
    6.  
    7. // specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims. 
    8. // you can add other claims here, if you want: 
    9. var claims = new list<claim>(); 
    10. foreach (var key in payload.keys) 
    11. var tempclaim = new claim(key, payload[key]?.tostring()); 
    12. claims.add(tempclaim); 
    13.  
    14. // create the jwt and write it to a string 
    15. var jwt = new jwtsecuritytoken( 
    16. issuer: null
    17. audience: null
    18. claims: claims, 
    19. notbefore: now, 
    20. expires: now.add(timespan.fromminutes(setting.expiresminute)), 
    21. signingcredentials: new signingcredentials(new symmetricsecuritykey(encoding.ascii.getbytes(setting.securitykey)), securityalgorithms.hmacsha256)); 
    22. var encodedjwt = new jwtsecuritytokenhandler().writetoken(jwt); 
    23. return encodedjwt; 

    从方法我们看到,我们传入的是负载这个片段,而失效时间与秘钥我们是放在了appsettings.json来进行配置的。使用di来获取配置文件中的节点值。

  2. 编写中间件
    我们都知道,中间件是core的管道模型组成部分,所以我们在中间件做验证,来判断每次请求用户是有有权限是有该webapi或者其他api。

    1. 中间件
      1. public jwtcustomerauthorizemiddleware(requestdelegate next, ioptions<jsonwebtokensetting> options, ijsonwebtokenvalidate jsonwebtokenvalidate, func<dictionary<string, string>, jsonwebtokensetting, bool> validatepayload, list<string> anonymouspathlist) 
      2. this._next = next; 
      3. this._setting = options.value; 
      4. this._jsonwebtokenvalidate = jsonwebtokenvalidate; 
      5. this._validatepayload = validatepayload; 
      6. this._anonymouspathlist = anonymouspathlist; 
      7.  
      8. public async task invoke(httpcontext context) 
      9. //jsonwebtokenvalidate 
      10. //若是路径可以匿名访问,直接跳过 
      11. if (_anonymouspathlist.contains(context.request.path.value)) 
      12. //还未验证 
      13. await _next(context); 
      14. return
      15. var result = context.request.headers.trygetvalue("authorization", out stringvalues authstr); 
      16. if (!result || string.isnullorempty(authstr.tostring())) 
      17. throw new unauthorizedaccessexception("未授权,请传递header头的authorization参数。"); 
      18.  
      19. //进行验证与自定义验证 
      20. result = _jsonwebtokenvalidate.validate(authstr.tostring().substring("bearer ".length).trim() 
      21. , _setting, _validatepayload); 
      22. if (!result) 
      23. throw new unauthorizedaccessexception("验证失败,请查看传递的参数是否正确或是否有权限访问该地址。"); 
      24.  
      25. await _next(context); 

    从代码来看,anonymouspathlist是url路径,若是在这个list内的url,便可直接跳过验证,
    接着将authstrtoken代入验证函数,validatepayload却是我们自代入的委托函数,用于服务器自定义验证。

    1. 验证
      验证方法,我只是做了签名验证与时间验证。并没有定得死死的,让用户*度的去进行验证。
      1. public bool validate(string encodejwt, jsonwebtokensetting setting, func<dictionary<string, string>, jsonwebtokensetting, bool> validatepayload) 
      2. if (string.isnullorwhitespace(setting.securitykey)) 
      3. throw new argumentnullexception("jsonwebtokensetting.securitykey"
      (0)
      打赏 ASP.NET Core的JWT的实现(中间件).md 微信扫一扫

      相关文章:

      版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

      发表评论

      ASP.NET Core的JWT的实现(中间件).md
      验证码: ASP.NET Core的JWT的实现(中间件).md