zoukankan      html  css  js  c++  java
  • 【从0开始.NET CORE认证】-4 开启OAuth认证之JWT

    系列

    【从0开始.NET CORE认证】-1 认识认证和授权

    【从0开始.NET CORE认证】-2 使用.Net Core Identity和EF Core

    【从0开始.NET CORE认证】-3 声明和策略授权

    回顾

    还是回到第三篇文章中,我们在第三篇文章简单的介绍了一下以下内容

    1. 怎么样结合Identity认证给IdentityUser签发Claims
    2. 怎么样使用基于策略的权限验证
    3. 怎么样使用基于角色的权限验证
    4. 怎么样对IdentityUser进行Claim操作

    其实第三篇并没有完全结束,只是没写完,有空再写。基于策略的权限验证能做很多有趣的事情。

    但是本篇开始会开启OAuth认证

    本次主要写一下内容

     OAuth介绍

    大家可以去百度,但是百度来的一大堆专业词汇,看的也非常迷惘!所以可以参考一下阮一峰大神的文章,关于解释OAuth是什么

    OAuth2.0的一个简单解释——阮一峰

    我这里还是简单的画个图方便大家理解

    1.这幅图就是传统的送货方式

     上面这幅图会带来什么问题?

    1. 业主告诉了快递员密码,在业主密码没更改的情况下,也就是说快递员约等于业主。无论是否上下班都可以自由出入小区
    2. 快递员泄露了密码,会导致其他人也能冒充业主闯过小区门禁系统
    3. 业主如果每次收完货就更改密码,下次还是要把新密码提供给快递员。每次更改极其麻烦

    所以为了解决问题,我们是不是中间加个流程,当快递员需要送货的时候,在小区门禁上提出申请,然后由业主同意,最后业主提供一个临时密码一样的东西给快递员,临时密码有有效期,1个小时就好了。这个问题是不是解决了

     增加了345步骤,既可以保证小区的安全性,又可以完成送货

    更多OAuth知识请参阅

    RFC-6749文档——英文版

    RFC-6749文档——中文版

    JWT介绍

    如果把上述流程应用到互联网开发中,现在开发模式大多属于前后端分离的状态,如果前端想要拿到后端的数据,后端说:你凭什么拿数据!依据我们前三篇讲的,我们可以用Cookies来证明自己。

    但是Cookies有个局限就是无法应用于分布式场景。

    所以引入了JWT的概念——JWT 全称Json Web Token,是一串字符串

    JWT分成三部分

    1. 头部
    2. 载荷
    3. 签名

    头部负责存储签名的算法和令牌的类型,载荷部分存储用户的个人信息。签名部分是对头部和载荷加密后生成的哈希字符。

    头部和载荷负责base64加密,签名使用哈希,最终构成一个长度很长的字符串。

    这个字符串就是快递员送货中的临时密码,在OAuth中也被称为access_token

    .Net Core Identity接入OAuth生成JWT

    .Net Core Identity已经实现了OAuth的框架,我们就用.Net Core Identity来实现一下OAuth

    新建一个项目,名称为:OAuthServer,然后稍微修改一下使其成为一个MVC页面,增加一个Index页面和Secert页面,其中Secert页面需要授权访问

    使用JWT需要引用以下扩展包

    Microsoft.AspNetCore.Authentication.JwtBearer

    在添加一个Login接口,负责颁发jwt

     1 public IActionResult Login()
     2         {
     3             var claim = new[]
     4             {
     5                 new Claim(JwtRegisteredClaimNames.Sub,"test"),
     6                 new Claim("test","test123")
     7             };
     8 
     9             var keybytes = Encoding.UTF8.GetBytes(Constants.key);
    10             var seckey = new SymmetricSecurityKey(keybytes);
    11             var alorgthim = SecurityAlgorithms.HmacSha256;
    12             var credential = new SigningCredentials(seckey, alorgthim);
    13 
    14             var token = new JwtSecurityToken(Constants.Issuer, Constants.Audiance, claim,
    15                 notBefore: DateTime.Now,
    16                 expires: DateTime.Now.AddHours(2),
    17                 signingCredentials: credential
    18                 );
    19 
    20             var access_token = new JwtSecurityTokenHandler().WriteToken(token);
    21             return Ok(new { access_token });
    22         }

    其中Constrants类是我自定义的一个类

     1 public class Constants
     2     {
     3 
     4         public const string Issuer = "http://localhost:8266";
     5 
     6         public const string Audiance = "http://localhost:8266";
     7 
     8         public const string key = "private_key_should_set_longer";
     9 
    10     }

    运行,访问/Home/Login接口

    发现是可以生成JWT格式的Token了。

    把拿到的token放到jwt.io解析一下,看下是什么东西

     可以看到,如我们上文介绍的一样,分成三个部分,头部,载荷和签名

    使用JWT访问被保护的资源

    这个时候需要使用一下测试工具POSTMAN,有关如果在http头部请求加入验证,请查阅百度,本处不再讲述

    用户提交了一个jwt格式的token过来,我们肯定是需要进行核验的,如果我们不进行核验,用户随随便便就提交过来,岂不是保护资源约等于没保护?

    在Startup.cs文件中修改一下代码

     1 services.AddAuthentication("OAuth")
     2                 .AddJwtBearer("OAuth",config=> {
     3                     var keybytes = Encoding.UTF8.GetBytes(Constants.key);
     4                     var seckey = new SymmetricSecurityKey(keybytes);
     5                     config.TokenValidationParameters = new TokenValidationParameters
     6                     {
     7                         ValidIssuer = Constants.Issuer,
     8                         ValidAudience = Constants.Audiance,
     9                         IssuerSigningKey = seckey,
    10                     };
    11                 });

    然后我们用postman测试一下

    可以发现成功访问。

    把Token放到url连接里面

    平常开发接口,有些时候为了方便,不会去对http的头部进行设置。所以会选择把token放到url参数里面,这种情况怎么处理呢?

    只需要更改一下代码就行了

     1 services.AddAuthentication("OAuth")
     2                 .AddJwtBearer("OAuth",config=> {
     3                     config.Events = new JwtBearerEvents()
     4                     {
     5                         OnMessageReceived = context =>
     6                         {
     7                             if (context.Request.Query.ContainsKey("access_token"))
     8                             {
     9                                 context.Token = context.Request.Query["access_token"];
    10                             }
    11                             return Task.CompletedTask;
    12                         }
    13                     };
    14                     var keybytes = Encoding.UTF8.GetBytes(Constants.key);
    15                     var seckey = new SymmetricSecurityKey(keybytes);
    16                     config.TokenValidationParameters = new TokenValidationParameters
    17                     {
    18                         ValidIssuer = Constants.Issuer,
    19                         ValidAudience = Constants.Audiance,
    20                         IssuerSigningKey = seckey,
    21                     };
    22                 });

    只需要侦听OnMessageReceived事件,当请求的url中包含access_token就把它的值赋给上下文中的token

    运行看下:

     可以发现,成功访问。

    结束

    好了,本章的JWT知识就到这里。

  • 相关阅读:
    Codeforces-859C Pie Rules(dp)
    Codeforces-550D Regular Bridge
    Codeforces-534D Handshakes
    抽象类
    内部类
    接口
    初始化
    this 和super
    数据库测试的测试点
    数据库测试的主要内容
  • 原文地址:https://www.cnblogs.com/lihuadeblog/p/12354091.html
Copyright © 2011-2022 走看看