当前位置: 首页 > news >正文

网站关键词优化排名推荐重庆网站建设qq群

网站关键词优化排名推荐,重庆网站建设qq群,嘉瑞建设集团有限公司网站,上海低价网站建设翻译自 Mohamad Lawand 2021年1月25日的文章 《Refresh JWT with Refresh Tokens in Asp Net Core 5 Rest API Step by Step》 [1]在本文中#xff0c;我将向您演示如何在 Asp.Net Core REST API 中将 Refresh Token 添加到 JWT 身份验证。我们将覆盖的一些主题包含#xff1… 翻译自 Mohamad Lawand 2021年1月25日的文章 《Refresh JWT with Refresh Tokens in Asp Net Core 5 Rest API Step by Step》 [1]在本文中我将向您演示如何在 Asp.Net Core REST API 中将 Refresh Token 添加到 JWT 身份验证。我们将覆盖的一些主题包含Refresh Token、一些新的 Endpoints 功能和 JWTJSON Web Token。你也可以在 YouTube 上观看完整的视频[2]还可以下载源代码[3]。这是 REST API 开发系列的第三部分前面还有Part 1Asp.Net Core 5 REST API - Step by StepPart 2Asp.Net Core 5 REST API 使用 JWT 身份验证 - Step by Step我将基于在上一篇文章中创建的 Todo REST API 应用程序进行当前的讲述。您可以通过阅读上一篇文章并与我一起构建应用程序或者可以从 github 下载上一篇中的源代码。在开始实现 Refresh Token 功能之前让我们先来了解一下 Refresh Token 的运行逻辑是怎样的。本质上JWT token 有一个过期时间时间越短越安全。在 JWT token 过期后有两种方法可以获取新的 token要求用户重新登录这不是一个好的用户体验。使用 Refresh Token 自动重新验证用户并生成新的 JWT token。那么Refresh Token 是什么呢一个 Refresh Token 可以是任何东西从字符串到 Guid 到任意组合只要它是唯一的。为什么短暂生命周期的 JWT token 很重要这是因为如果有人窃取了我们的 JWT token 并开始请求我们的服务器那么该 token 在过期变得不可用之前只会持续一小段时间。获取新 token 的唯一方法是使用 Refresh Token 或登录。另一个重点是如果用户更改了密码则根据之前的用户凭据生成的所有 token 会怎样呢。我们并不想使所有会话都失效我们只需请求刷新 Token那么将生成一个基于新凭证的新 JWT token。另外实现自动刷新 token 的一个好办法是在客户端发出每个请求之前都需要检查 token 的过期时间如果已过期我们就请求一个新的 token否则就使用现有的 token 执行请求。因此我们将在应用程序中添加一个 Refresh Token而不仅仅是在每次授权时都只生成一个 JWT token。那就让我们开始吧首先我们将更新 Startup 类通过将 TokenValidationParameters 添加到依赖注入容器使它在整个应用程序中可用。var key Encoding.ASCII.GetBytes(Configuration[JwtConfig:Secret]);var tokenValidationParams new TokenValidationParameters {ValidateIssuerSigningKey true,IssuerSigningKey new SymmetricSecurityKey(key),ValidateIssuer false,ValidateAudience false,ValidateLifetime true,RequireExpirationTime false,ClockSkew TimeSpan.Zero };services.AddSingleton(tokenValidationParams);services.AddAuthentication(options {options.DefaultAuthenticateScheme JwtBearerDefaults.AuthenticationScheme;options.DefaultScheme JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(jwt {jwt.SaveToken true;jwt.TokenValidationParameters tokenValidationParams; }); 更新完 Startup 类以后我们需要更新 AuthManagementController 中的 GenerateJwtToken 函数将 TokenDescriptor 的 Expires 值从之前的值更新为 30 秒比较合理的值为 5~10 分钟这里设置为 30 秒只是作演示用我们需要把它指定的更短一些。译者注实际使用时可以在 appsettings.json 中为 JwtConfig 添加一个代表 token 过期时间的 ExpiryTimeFrame 配置项对应的在 JwtConfig 类中添加一个 ExpiryTimeFrame 属性然后赋值给 TokenDescriptor 的 Expires这样 token 的过期时间就变得可配置了。private string GenerateJwtToken(IdentityUser user) {var jwtTokenHandler new JwtSecurityTokenHandler();var key Encoding.ASCII.GetBytes(_jwtConfig.Secret);var tokenDescriptor new SecurityTokenDescriptor{Subject new ClaimsIdentity(new[]{new Claim(Id, user.Id),new Claim(JwtRegisteredClaimNames.Email, user.Email),new Claim(JwtRegisteredClaimNames.Sub, user.Email),new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())}),Expires DateTime.UtcNow.AddSeconds(30), // 比较合理的值为 5~10 分钟这里设置 30 秒只是作演示用SigningCredentials new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)};var token jwtTokenHandler.CreateToken(tokenDescriptor);var jwtToken jwtTokenHandler.WriteToken(token);return jwtToken; } 接下来的步骤是更新 Configuration 文件夹中的 AuthResult我们需要为 Refresh Token 添加一个新属性// Configuration\AuthResult.cspublic class AuthResult {public string Token { get; set; }public string RefreshToken { get; set; }public bool Success { get; set; }public Liststring Errors { get; set; } } 我们将在 Models/DTOs/Requests 中添加一个名为 TokenRequest 的新类该类负责接收稍后我们将创建的新 Endpoint 的请求参数用于管理刷新 Token。// Models\DTOs\Requests\TokenRequest.cspublic class TokenRequest {/// summary/// 原 Token/// /summary[Required]public string Token { get; set; }/// summary/// Refresh Token/// /summary[Required]public string RefreshToken { get; set; } } 下一步是在我们的 Models 文件夹中创建一个名为 RefreshToken 的新模型。// Models\RefreshToken.cspublic class RefreshToken {public int Id { get; set; }public string UserId { get; set; } // 连接到 ASP.Net Identity User Idpublic string Token { get; set; } // Refresh Tokenpublic string JwtId { get; set; } // 使用 JwtId 映射到对应的 tokenpublic bool IsUsed { get; set; } // 如果已经使用过它我们不想使用相同的 refresh token 生成新的 JWT tokenpublic bool IsRevorked { get; set; } // 是否出于安全原因已将其撤销public DateTime AddedDate { get; set; }public DateTime ExpiryDate { get; set; } // refresh token 的生命周期很长可以持续数月[ForeignKey(nameof(UserId))]public IdentityUser User {get;set;} } 添加 RefreshToken 模型后我们需要更新 ApiDbContext 类public virtual DbSetRefreshToken RefreshTokens { get; set; } 现在让我们为 ApiDbContext 创建数据库迁移以便可以反映数据库中的更改dotnet ef migrations add Added refresh tokens table dotnet ef database update 下一步是在 AuthManagementController 中创建一个新的名为 RefreshToken 的 Endpoind。需要做的第一件事是注入 TokenValidationParametersprivate readonly UserManagerIdentityUser _userManager; private readonly JwtConfig _jwtConfig; private readonly TokenValidationParameters _tokenValidationParams; private readonly ApiDbContext _apiDbContext;public AuthManagementController(UserManagerIdentityUser userManager,IOptionsMonitorJwtConfig optionsMonitor,TokenValidationParameters tokenValidationParams,ApiDbContext apiDbContext) {_userManager userManager;_jwtConfig optionsMonitor.CurrentValue;_tokenValidationParams tokenValidationParams;_apiDbContext apiDbContext; } 注入所需的参数后我们需要更新 GenerateJwtToken 函数以包含 Refresh Tokenprivate async TaskAuthResult GenerateJwtToken(IdentityUser user) {var jwtTokenHandler new JwtSecurityTokenHandler();var key Encoding.ASCII.GetBytes(_jwtConfig.Secret);var tokenDescriptor new SecurityTokenDescriptor{Subject new ClaimsIdentity(new[]{new Claim(Id, user.Id),new Claim(JwtRegisteredClaimNames.Email, user.Email),new Claim(JwtRegisteredClaimNames.Sub, user.Email),new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())}),Expires DateTime.UtcNow.AddSeconds(30), // 比较合理的值为 5~10 分钟这里设置 30 秒只是作演示用SigningCredentials new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)};var token jwtTokenHandler.CreateToken(tokenDescriptor);var jwtToken jwtTokenHandler.WriteToken(token);var refreshToken new RefreshToken(){JwtId token.Id,IsUsed false,IsRevorked false,UserId user.Id,AddedDate DateTime.UtcNow,ExpiryDate DateTime.UtcNow.AddMonths(6),Token RandomString(25) Guid.NewGuid()};await _apiDbContext.RefreshTokens.AddAsync(refreshToken);await _apiDbContext.SaveChangesAsync();return new AuthResult(){Token jwtToken,Success true,RefreshToken refreshToken.Token}; }private string RandomString(int length) {var random new Random();var chars ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;return new string(Enumerable.Repeat(chars, length).Select(x x[random.Next(x.Length)]).ToArray()); } 现在让我们更新两个现有 Action 的返回值因为我们已经更改了 GenerateJwtToken 的返回类型Login Actionreturn Ok(await GenerateJwtToken(existingUser)); Register Actionreturn Ok(await GenerateJwtToken(newUser)); 然后我们可以开始构建 RefreshToken Action[HttpPost] [Route(RefreshToken)] public async TaskIActionResult RefreshToken([FromBody] TokenRequest tokenRequest) {if (ModelState.IsValid){var result await VerifyAndGenerateToken(tokenRequest);if (result null){return BadRequest(new RegistrationResponse(){Errors new Liststring() {Invalid tokens},Success false});}return Ok(result);}return BadRequest(new RegistrationResponse(){Errors new Liststring() {Invalid payload},Success false}); }private async TaskAuthResult VerifyAndGenerateToken(TokenRequest tokenRequest) {var jwtTokenHandler new JwtSecurityTokenHandler();try{// Validation 1 - Validation JWT token format// 此验证功能将确保 Token 满足验证参数并且它是一个真正的 token 而不仅仅是随机字符串var tokenInVerification jwtTokenHandler.ValidateToken(tokenRequest.Token, _tokenValidationParams, out var validatedToken);// Validation 2 - Validate encryption alg// 检查 token 是否有有效的安全算法if (validatedToken is JwtSecurityToken jwtSecurityToken){var result jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase);if (result false){return null;}}// Validation 3 - validate expiry date// 验证原 token 的过期时间得到 unix 时间戳var utcExpiryDate long.Parse(tokenInVerification.Claims.FirstOrDefault(x x.Type JwtRegisteredClaimNames.Exp).Value);var expiryDate UnixTimeStampToDateTime(utcExpiryDate);if (expiryDate DateTime.UtcNow){return new AuthResult(){Success false,Errors new Liststring() {Token has not yet expired}};}// validation 4 - validate existence of the token// 验证 refresh token 是否存在是否是保存在数据库的 refresh tokenvar storedRefreshToken await _apiDbContext.RefreshTokens.FirstOrDefaultAsync(x x.Token tokenRequest.RefreshToken);if (storedRefreshToken null){return new AuthResult(){Success false,Errors new Liststring() {Refresh Token does not exist}};}// Validation 5 - 检查存储的 RefreshToken 是否已过期// Check the date of the saved refresh token if it has expiredif (DateTime.UtcNow storedRefreshToken.ExpiryDate){return new AuthResult(){Errors new Liststring() { Refresh Token has expired, user needs to re-login },Success false};}// Validation 6 - validate if used// 验证 refresh token 是否已使用if (storedRefreshToken.IsUsed){return new AuthResult(){Success false,Errors new Liststring() {Refresh Token has been used}};}// Validation 7 - validate if revoked// 检查 refresh token 是否被撤销if (storedRefreshToken.IsRevorked){return new AuthResult(){Success false,Errors new Liststring() {Refresh Token has been revoked}};}// Validation 8 - validate the id// 这里获得原 JWT token Idvar jti tokenInVerification.Claims.FirstOrDefault(x x.Type JwtRegisteredClaimNames.Jti).Value;// 根据数据库中保存的 Id 验证收到的 token 的 Idif (storedRefreshToken.JwtId ! jti){return new AuthResult(){Success false,Errors new Liststring() {The token doesnt mateched the saved token}};}// update current token // 将该 refresh token 设置为已使用storedRefreshToken.IsUsed true;_apiDbContext.RefreshTokens.Update(storedRefreshToken);await _apiDbContext.SaveChangesAsync();// 生成一个新的 tokenvar dbUser await _userManager.FindByIdAsync(storedRefreshToken.UserId);return await GenerateJwtToken(dbUser);}catch (Exception ex){if (ex.Message.Contains(Lifetime validation failed. The token is expired.)){return new AuthResult(){Success false,Errors new Liststring() {Token has expired please re-login}};}else{return new AuthResult(){Success false,Errors new Liststring() {Something went wrong.}};}} }private DateTime UnixTimeStampToDateTime(long unixTimeStamp) {var dateTimeVal new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);dateTimeVal dateTimeVal.AddSeconds(unixTimeStamp).ToLocalTime();return dateTimeVal; } 最后我们需要确保一切可以正常构建和运行。dotnet build dotnet run 当我们确定一切 OK 后我们可以使用 Postman 测试应用程序测试场景如下所示登录生成带有刷新令牌的 JWT 令牌 ⇒ 成功不等待令牌过期而直接尝试刷新令牌 ⇒ 失败等待 JWT 令牌过期然后请求刷新令牌 ⇒ 成功重新使用相同的刷新令牌 ⇒ 失败感谢您花时间阅读本文。本文是 API 开发系列的第三部分你可以通过下面链接阅读前两部分Part 1Asp.Net Core 5 REST API - Step by StepPart 2Asp.Net Core 5 REST API 使用 JWT 身份验证 - Step by Step相关链接https://dev.to/moe23/refresh-jwt-with-refresh-tokens-in-asp-net-core-5-rest-api-step-by-step-3en5 Refresh JWT with Refresh Tokens in Asp Net Core 5 Rest API Step by Step ↩︎https://youtu.be/T_Hla1WzaZQ ↩︎https://github.com/mohamadlawand087/v8-refreshtokenswithJWT ↩︎作者 Mohamad Lawand译者 技术译民出品 技术译站https://ITTranslator.cn/END
http://www.pierceye.com/news/384443/

相关文章:

  • 简单网站建设合同贵州省高层建筑信息平台
  • 手机网站登录模板电视剧百度风云榜
  • 一嗨租车网站建设的功能特色梅林做网站
  • 网站关于我们怎么做36氪 wordpress 模板
  • 医疗网站建设计划书菏泽手机网站建设
  • 南京外贸网站建设哪家好免费网站建站方法
  • 文化馆建设网站网架公司有哪些
  • 企业如何申请网站51网站空间相册
  • 自己电脑做网站服务器系统网站建设违约交付
  • 什么叫域名访问网站wordpress app 接口
  • 学生网站建设实训总结工信部备案号查询平台
  • 凡科建站如何制作论坛备案网站需要多久
  • 网站建设的公司哪家是上市公司专业外贸网站制作
  • 建站公司杭州免费投票网站制作
  • 网站优化公司效果网络营销毕业后做什么工作
  • 移动互联网的应用论文可以优化网络的软件
  • 网站建设软件哪个最好郑州广告设计与制作公司
  • 浦口区网站建设售后保障如何维护网站
  • 企业网站建设 安全合肥做网站加盟
  • 水果网络营销策划方案电商网站怎样优化
  • 免费数据源网站wordpress主页面
  • 做网站百度收费吗青岛冠通市政建设有限公司网站
  • 菜鸟建网站福建福州罗源建设局网站
  • 企业内网网站制作自己的网站多少钱
  • 关于公司网站建设的申请wordpress站群功能
  • 外贸做企业什么网站珠海的网站建设
  • 做网站教程百度云外贸soho建站公司
  • 上海市网站建设网站增加导航栏
  • 电子政务网站模版网站制作排名优化
  • 大足网站建设wordpress本地很慢