今天学习下JWT,遇到了两个坑爹问题,这里记录下。在 ASP.NET Core 中,受权的设置方式有两种,可使用角色,也可使用策略,这里也将简单举例角色、策略的使用。html
JWT这里不作介绍,若是想了解更多,请看https://www.jianshu.com/p/a12fc67c9e05,https://www.cnblogs.com/CreateMyself/p/11123023.html ,这两篇都讲解的很好,这里只写实际的使用和遇到的问题。git
jwt中key必须16位以上,不然长度不够会抛出异常,异常代码以下github
System.ArgumentOutOfRangeException HResult=0x80131502 Message=IDX10603: Decryption failed. Keys tried: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'. Exceptions caught: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'. token: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]' Source=Microsoft.IdentityModel.Tokens StackTrace: at Microsoft.IdentityModel.Tokens.SymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures) ....................
在Startup.cs中的Configure中添加app.UseAuthentication();新建立.net core项目的时候,会自动添加受权app.UseAuthorization();可是JWT实际上是一种认证,准确;来讲是登陆的过程,须要用户名和密码的认证。算法
例如:你要登录论坛,输入用户名张三,密码1234,密码正确,证实你张三确实是张三,这就是 认证authentication;那么是否有删除添加等的操做,这就是受权authorizationjson
//appsettings.json中增长配置信息
"JwtSettings": { "Issuer": "https://localhost:44378/", "Audience": "https://localhost:44378/", "SecretKey": "1234567890123456" }
// Startup.cs中增长JWT的设置
services.AddAuthentication(options => { //认证middleware配置 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(o => { //主要是jwt token参数设置 o.TokenValidationParameters = new TokenValidationParameters { //Token颁发机构 ValidIssuer = jwtSettings.Issuer, //颁发给谁 ValidAudience = jwtSettings.Audience, //这里的key要进行加密,须要引用Microsoft.IdentityModel.Tokens IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)), ValidateIssuerSigningKey = true, //是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比 ValidateLifetime = true, //容许的服务器时间偏移量 ClockSkew = TimeSpan.Zero }; });
// Controller中获取token
[HttpPost] public IActionResult Token(LoginModel login) { _logger.LogInformation($"获取Token:User:{login.User}"); if (string.IsNullOrEmpty(login.User) || string.IsNullOrEmpty(login.Password))//判断帐号密码是否正确 { return BadRequest(); } var claim = new List<Claim>{ new Claim(ClaimTypes.Name,login.User), new Claim(ClaimTypes.Role,"Test") }; //创建增长策略的受权 if (login.User == "Test") claim.Add(new Claim("Test", "Test")); if (login.User == "Test1") claim.Add(new Claim("Test", "Test1")); if (login.User == "Test2") claim.Add(new Claim("Test", "Test2")); if (login.User == "Test3") claim.Add(new Claim("Test", "Test3")); //对称秘钥 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey)); //签名证书(秘钥,加密算法) var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //生成token [注意]须要nuget添加Microsoft.AspNetCore.Authentication.JwtBearer包,并引用System.IdentityModel.Tokens.Jwt命名空间 var token = new JwtSecurityToken(_jwtSettings.Issuer, _jwtSettings.Audience, claim, DateTime.Now, DateTime.Now.AddMinutes(30), creds); return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) }); }
[HttpGet] [Authorize(Roles ="Test")] public ActionResult<string> AuthValue() { var name = User.FindFirst(ClaimTypes.Name)?.Value; var role = User.FindFirst(ClaimTypes.Role)?.Value; _logger.LogInformation($"权限登陆,用户名:{name},角色:{role}"); return $"权限登陆,用户名:{name},角色:{role}"; }
Roles角色若是有多个,能够以逗号隔开。
//Startup.cs中添加策略
services.AddAuthorization(options => { options.AddPolicy("OnlyTestAccess", policy => policy.RequireClaim("Test", new string[] { "Test1", "Test2" })); options.AddPolicy("DepartmentAccess", policy => policy.RequireClaim("Department")); });
// 方法上增长策略
[HttpGet] [Authorize(Policy = "OnlyTestAccess")] public ActionResult<string> AuthExtensionValue() { var name = User.FindFirst(ClaimTypes.Name)?.Value; var role = User.FindFirst(ClaimTypes.Role)?.Value; _logger.LogInformation($"基于策略的登陆,用户名:{name},角色:{role}"); return $"基于策略的登陆,用户名:{name},角色:{role}"; }
https://github.com/jasonhua95/samll-project/tree/master/JwtApiDemo服务器