.net core中使用jwt进行认证
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
- Payload
- Signature
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再次访问
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· DeepSeek本地性能调优
· 一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略