netCore最简单的Jwt的demo

Posted qintai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了netCore最简单的Jwt的demo相关的知识,希望对你有一定的参考价值。

netCore中,微软把授权和认证分开了,先授权,再进行认证,本篇文章,用来介绍JWtNetCore的使用

 

根据不同的登录用户而言,拥有着不一样的权限,在介绍之前要知道一下几点

 

1.知道identity是什么,他是个身份

 

2.知道 Claim 是什么,可以理解为证件

 

3.知道授权里面的 Policy,授权策略

 

一:先安装  Microsoft.AspNetCore.Authentication.JwtBearer

技术图片

 

 

二:在 Startup

 

技术图片
 1    public Startup(IConfiguration configuration)
 2      {
 3             Configuration = configuration;
 4      }
 5 
 6         public IConfiguration Configuration { get; }
 7         
 8         public void ConfigureServices(IServiceCollection services)
 9         {
10             services.AddMvc();
11 
12             //授权
13             services.AddAuthorization(options =>
14             {
15                 // 添加授权的策略, 
16                 //通过代码,可以看出 一个授权策略是可以包含多个用户的角色的,是不是有点像“角色用户分组”
17                 options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
18                 options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("test", "System")); // 就像是 SystemOrAdmin就是组名,成员有角色test和角色System
19             });
20 
21             //认证
22             services.AddAuthentication(options =>
23             {
24                 options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
25                 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
26             })
27             .AddJwtBearer(cfg =>
28             {
29                 cfg.RequireHttpsMetadata = false;// 获取或设置元数据地址或权限是否需要https。这个  默认值为true。这应该只在开发环境中禁用。
30                 cfg.SaveToken = true; //定义承载令牌是否应存储在Microsoft.aspnetcore.http.authentication.authenticationproperties中   在成功授权之后。
31 
32                 // TokenValidationParameters:获取或设置用于验证标识令牌的参数。
33                 cfg.TokenValidationParameters = new TokenValidationParameters()
34                 {
35                     ValidIssuer = Configuration["Tokens:Issuer"],  //获取或设置表示将使用的有效颁发者的System.String。  检查令牌的颁发者。
36                     ValidAudience = Configuration["Tokens:Issuer"],  //获取或设置一个字符串,该字符串表示将用于检查的有效访问群体。  反对代币的观众。
37                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))   // 获取或设置要使用的Microsoft.IdentityModel.Tokens.SecurityKey。用于签名验证。
38                 };
39                 JwtBearerEvents events = new JwtBearerEvents
40                 {
41                     //请求出现异常时,调用这个
42                     OnAuthenticationFailed = context =>
43                     {
44                     // 判断token是否已经过期
45                     if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
46                         {
47                             context.Response.Headers.Add("Token-Expired", "true"); //如果已经过期,加一个header头部
48 
49                         using (StreamWriter streamWriter = new StreamWriter(context.Response.Body, Encoding.UTF8))
50                                 streamWriter.Write("你的token已经过期了");
51 
52                         }
53                         return Task.CompletedTask;
54                     }
55                 };
56                 cfg.Events = events;
57             });
58         }
View Code

 

加入  app.UseAuthentication();  ,要在 app.UseMvc(); 之前

 

三:写个AuthController,写个登录方法

 

技术图片
 1     [HttpPost]
 2         public IActionResult Login([FromBody] AuthRequest authUserRequest)
 3         {
 4             if (authUserRequest == null)
 5                 return BadRequest("没找到登录用户");//Could not create token,返回 400 Bad Request
 6             if (authUserRequest.UserName != "test" || authUserRequest.Password != "test")
 7                 return BadRequest("用户名或者密码输入错误");//Could not create token
 8 
 9             // 1.写好这个证件中,有哪些信息,一个Claim 对象代表着一个证件中某一个信息
10             Claim[] claims = new[]
11             {
12                 new Claim(JwtRegisteredClaimNames.UniqueName, authUserRequest.UserName), //证件用户名
13                 new Claim(JwtRegisteredClaimNames.Sid, authUserRequest.UserId),//  证件Id   
14 
15                 new Claim(ClaimTypes.Role, "test") //证件的角色,以后控制器上就可以直接这样写 [Authorize(Roles = "test")]
16             };
17 
18 
19             // 2. 准备 安全密钥。
20             SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this._config["Tokens:Key"]));
21             //3.准备 数字签名的安全密钥、算法和摘要。
22             SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
23 
24             //4.实例化JWT得到token,
25             JwtSecurityToken jst = new JwtSecurityToken(
26                 issuer :  this._config["Tokens:Issuer"],
27                 audience:    this._config["Tokens:Issuer"],
28                 claims:    claims,
29                 expires:  DateTime.Now.AddMinutes(30),
30                 signingCredentials: creds
31             );
32 
33             // 5. 以精简序列化格式将JWT安全令牌序列化为WT。拿到最终的token
34             string token = new JwtSecurityTokenHandler().WriteToken(jst);
35 
36             return Ok(new
37             {
38                 token,
39                 expiration = jst.ValidTo //获取已转换为System.DateTime的“过期”声明{exp,“值”}的“值”。 假设‘value‘是unixepoch(UTC 1970 - 01 - 01t0:0:0z)之后的秒数。拿到过期的时间
40             });
41 
42         }
View Code

 

再写个需要授权才能访问的控制,ValuesController

 

 

技术图片
 1   [Route("api/[controller]")]
 2     //[Authorize]  这么写,完全就是一个检查token的作用,没有检查角色
 3     //[Authorize(Policy = "SystemOrAdmin")] 等价于 [Authorize("SystemOrAdmin")]
 4 
 5     //  [Authorize(Roles = "test")]
 6     //[Authorize(Policy = "SystemOrAdmin")]
 7     [Authorize("SystemOrAdmin")]
 8     public class ValuesController : Controller
 9     {
10         // GET api/values
11         [HttpGet]
12         public IEnumerable<string> Get()
13         {
14             return new string[] { "授权成功", "value2", "value3", "value4", "value5" };
15         }
16     }
View Code

 

技术图片

 

 

打开这个页面,直接点击GetData,由于没有授权,就报的401
GetData调用的接口是value控制器中的Get方法

技术图片

 

 当点击登录后,再点击Getdata就是成功的。如果当前登录用户的角色,没有认证成功,返回403给你

 

 要注意的是:[Authorize(Roles = "test")] ,表示当前  Claim.Role=“test”,才能进来,那么在登录的时候,就要当前登录成功的用户写进 Claim 中,以及当前登录用户所对应的权限

[Authorize(Policy = "SystemOrAdmin")]Policy 是一个授权策略,他里面包含着多中用户角色,就是某一组用户角色组名,他的配置也在 ConfigureServices 写好,   services.AddAuthorization ,添加授权里面,写上。

 

还有一点是,利用微软官方的认证机制,如果没有授权成功,及授权失败,他都是直接返回 Http状态码,但是你希望,返回一个view或者一段json?或者说是 把当前登录用户信息,写进HttpContex.User?

技术图片
1 这时候,就需要自己手动写个类,继承  IAuthorizationRequirement,
2 来完成 整个认证的过程,返回什么由自己定义
3 //注入 我们自定义的权限处理器,替换微软Core自带的 权限检查处理,
4 //PermissionHandler类是我们自定义认证逻辑类
5 services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
View Code

 

 

 

 

以上是关于netCore最简单的Jwt的demo的主要内容,如果未能解决你的问题,请参考以下文章

当角度应用已经使用JWT进行AJAX请求时,最简单的方法来保护浏览器请求?

JWT验证

SpringSecurity+JWT认证流程解析

ASP.NET Core 2.2 JWT 身份验证

在 Active Directory 环境中生成 JWT

ASP.NET Core 5.0 JWT 身份验证引发 401 代码 [重复]