时间:2020-09-06来源:www.pcxitongcheng.com作者:电脑系统城
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公用/专用密钥对对JWT进行签名。
传统token
当用登录成功后,服务端会根据用户的信息生成一个token,然后将token保存到redis中。当用户再次访问时会携带这个token访问,这时服务端会先去查一下redis,看有没有这个token或者是查看这个token是否过期,当redis中没有这个token时,登录验证失败,提示用户登录失败,否则直接放行。当然传统的token也有其一定的优势,比如说返回token能屏蔽用户的真实信息,临时且唯一。但当并发数量大的时候,这种模式存在的问题就是,用户一访问就去查redis,会增加redis的压力。
JWT
jwt通常由三部分组成分别是:
Header通常由两部分组成,令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。
{ "alg": "HS256", "typ": "JWT" }
Payload 令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。有以下三种类型:注册声明,公共声明和私人声明。
标准注册声明
iss:jwt的发行方 sub:jwt声明的主题 aud:jwt所面向的群体 exp:到期时间 nbf:(不早于)声明标识了JWT之前的时间不得接受处理
公共声明
使用JWT的人可以随意定义这些声明。主要包括用户的各种信息但要避免私密的信息
私密声明
私有声明是发布者和面向者所共同定义的声明
{ "phone": "1234567890", "name": "John Doe", "admin": true }
Signature
signature是一个签名信息,是对前两部分进行base64加密和secret一起进行组合加密,这里的secret就相当于一个加盐的操作
例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
最后生成的token就是下面的这种格式
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoid293byIsInN1YiI6InN1Yk5hbWUiLCJuYmYiOiIxNTk5MzY3NjUwIiwiZXhwIjoxNTk5MzY3OTUwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQ5OTk5IiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo0OTk5OSJ9.cqn55T-VFKkKuG2hSdQ_WNqjBhYiK9o3LvK-E9a893Y
通过jwt的工作原理,我们会发现jwt与传统的token相比,jwt不用去redis中查询对应的token信息而是通过定义的加密算法去进行校验,这一块算是对token的重大改进吧
.Net Core中使用JWT
1.通过nuget安装 Microsoft.AspNetCore.Authentication.JwtBearer
2.在ConfigureServices中进行相应的注册
//使用jwt进行认证 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, //是否验证超时 当设置exp和nbf时有效 ValidateIssuerSigningKey = true, ////是否验证密钥 ValidAudience = "http://localhost:49999",//Audience ValidIssuer = "http://localhost:49998",//Issuer,这两项和登陆时颁发的一致 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("123456888jdijxhelloworldprefect")), //拿到SecurityKey //缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟 //注意这是缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟 ClockSkew = TimeSpan.FromMinutes(5) //设置过期时间 }; });
2.在Configure中添加认证授权中间件
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseAuthentication(); //认证 app.UseAuthorization(); //授权 app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
3.登录成功后生成token并返回客户端
[HttpPost] public IActionResult Login(string username,string password) { var user = bll.GetUser(username, password); if (user != null) { var claims = new[] { new Claim(ClaimTypes.Name,username), new Claim(JwtRegisteredClaimNames.Sub, "subName"), new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"), //NotBefore token生效时间 new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddMilliseconds(1)).ToUnixTimeSeconds()}") //Expiration 到期时间,按秒数计算 }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("123456888jdijxhelloworldprefect")); //key的长度要超过16个字符,不然回抛出异常 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: "http://localhost:49999", //颁发token的web应用程序 audience: "http://localhost:49998", claims: claims, expires: DateTime.Now.AddMinutes(5), signingCredentials: creds); return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token),success=true,message="登录成功" }); } else { return BadRequest(new { success = false, message = "登录失败,请重试" }); } }
用postman进行测试 1.调用登录接口生成token
2.不加token去访问保护的资源
3.带上生成的token再次访问
2020-09-06
graph attention network(ICLR2018)官方代码详解(te4nsorflow)2020-08-20
.Net Core3.1 + EF Core + LayUI 封装的MVC版后台管理系统2020-08-20
.net core的web项目发布到服务器环境的处理步骤在.NET Core中使用MongoDB明细教程(3):Skip, Sort, Limit, Projections...
2020-08-20