公司网站设计与开发,wordpress 执行sql update,百度关键词排名怎么查,新乡商城网站建设哪家专业最近#xff0c;团队的小伙伴们在做项目时#xff0c;需要用到JWT认证。遂根据自己的经验#xff0c;整理成了这篇文章#xff0c;用来帮助理清JWT认证的原理和代码编写操作。第一部分#xff1a;Dotnet core使用JWT认证授权最佳实践(一)#xff08;接上文#xff09;测… 最近团队的小伙伴们在做项目时需要用到JWT认证。遂根据自己的经验整理成了这篇文章用来帮助理清JWT认证的原理和代码编写操作。第一部分Dotnet core使用JWT认证授权最佳实践(一)接上文测试运行% dotnet run
等程序运行起来后在浏览器输入http://localhost:5000/swagger/会进到Swagger的API界面。选择requestToken点击按钮”Try it out“-”Execute“可以看到运行结果[eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoic3RyaW5nIiwiZXhwIjoxNTg5MzgxMzQ4LCJpc3MiOiJXYW5nUGx1cyJ9.ojGuWUk9i2Vp5qu3s2UZSLC64Sm95Cao2eGF3GDVvec,123456]
好吧不要在意这个返回的格式。返回的两个串中第一个就是Token第二个是refreshToken。 到这儿我们成功拿到了用户的Token。四、Token认证拿到Token后我们就可以进行认证操作了。既然是认证那应该在每个API上进行。所以认证的过程不会放到控制器里而应该以MiddleWare的方式放到主流程中。这个MiddleWareMicrosoft.AspNetCore.Authentication.JwtBearer库已经帮我们做好了。我们只需要配置就好。在Startup.cs中ConfigureServices方法里添加以下内容services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(option
{option.RequireHttpsMetadata false;option.SaveToken true;var token Configuration.GetSection(tokenParameter).GettokenParameter();option.TokenValidationParameters new TokenValidationParameters{ValidateIssuerSigningKey true,IssuerSigningKey new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.Secret)),ValidIssuer token.Issuer,ValidateIssuer true,ValidateAudience false,};
});
这里面有几个参数需要注意RequireHttpsMetadata: 限定认证操作是否必须通过https来做这个要跟随项目在生产环境中的运行情况来定。如果WebServer是我前文15分钟从零开始搭建支持10w用户的生产环境(三)中介绍的Jexus采用对外https对内http的方式那这儿可以设为false。SaveToken: 决定Token在认证完成后是否需要保存到上下文里并向后传。这个设置也要看应用。我们Token生成后用户的相关信息已经包含在里面了。API里如果有涉及用户的操作按理可以不用往API里传相关用户的参数。一方面不安全另一方面代码也不好看。这时就可以把这个参数设为True然后API从上下文中直接取用户信息。在Startup.cs里Configure方法中打开认证app.UseAuthentication();
app.UseAuthorization();这两步完成我们就完成的认证的开发工具。用别人的轮子还是很爽的虽然轮子的挑选工作很复杂很费力。 设置API认证。在这个Demo里我们选代码生成时给的WeatherForecastController下的Get方法来测试。在方法前边我们加上Authorize[HttpGet]
[Authorize]
public IEnumerableWeatherForecast Get()
...
测试运行。启动程序跟上一章的方式一样。程序运行后打开http://localhost:5000/swagger/进入WeatherForecast点”Try it out“-”Execute“我们会得到一个401 - Error: Unauthorized的返回因为我们没有做认证。下面测试做认证后的访问。先去requestToken拿一个TokenrefreshToken这章不用在前边加“Bearer ”拼成一个串Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoic3RyaW5nIiwiZXhwIjoxNTg5MzgxMzQ4LCJpc3MiOiJXYW5nUGx1cyJ9.ojGuWUk9i2Vp5qu3s2UZSLC64Sm95Cao2eGF3GDVvec
要注意Bearer后边要跟一个空格。这个串的格式是Bearer 空格 Token。在页面的右上角有一个“Authorize”点进去在Value输入框中粘贴上面拼好的串然后点按钮“Authorize”保存认证信息。下面进入WeatherForecast点”Try it out“-”Execute“这时候我们就能拿到正确的返回数据。五、扩展用户角色认证在上一章中我们实现了用户的认证。但这个认证有个不漂亮的地方用户只简单的被认证系统分成了通过认证的和不通过认证的。在实际项目中我们有时候会有这样的需求对于某个API我们希望只允许具有某种角色权限的用户去访问。下面我们对这个项目进行小量的修改以完成这个需求。在给用户签发Token的过程中加入用户的角色数据。在AuthenticationController的RequestToken中我们构建了一个用户的Claimsvar claims new[]
{new Claim(ClaimTypes.Name,request.username),
};
就是这儿。我们在这儿加入用户的角色var claims new[]
{new Claim(ClaimTypes.Name,request.username),new Claim(ClaimTypes.Role, testUser),
};
实际应用中这个角色的名称可以根据需要从用户系统中拿来。在这个Demo里就直接写成个字符串了。就是说有一个角色叫testUser。给API增加认证的角色要求[HttpGet]
[Authorize(RolestestUser)]
public IEnumerableWeatherForecast Get()
...
在这里这个RolestestUser里的testUser就是这个方法授权所对应的角色名称。测试运行按正常的步骤取Token拼串保存认证信息然后去运行WeatherForecastAPI能正常返回。我们可以把代码中的testUser改成别的字符串进行测试会返回403 - Error: Forbidden错误。 增加角色认证成功。六、刷新TokenToken过期后就需要刷新。当然我们可以把Token设成永远不过期但这不是个安全的做法。还可以在Token过期后重新请求一个新Token但这样做会显得Low。赏心悦目的做法是用refreshToken来刷新Token。设置refreshToken的过期时间长于Token。Token过期后让用户提交Token和refreshToken到服务器服务器验证Token是否合法并从中提取用户信息根据用户信息和refreshToken核验是否匹配。如果匹配就重新生成Token给用户。至于refreshToken的过期时长和是否需要在刷新Token时也刷新refreshToken就看心情了没有固定的做法。我自己的项目中Token是2小时过期refreshToken是24小时过期。在Token刷新时如果refreshToken的过期时间少于6小时则刷新refreshToken。供参考。 下面按这个方式做一下刷新Token。在DTOModels下建一个RefreshTokenDTO用作API的输入参数using System;namespace demo.DTOModels
{public class RefreshTokenDTO{public string Token { get; set; } public string refreshToken { get; set; }}
在AuthenticationController里创建一个RefreshToken的API并补齐验证代码[HttpPost, Route(refreshToken)]
public ActionResult RefreshToken([FromBody]RefreshTokenDTO request)
{if(request.Token null request.refreshToken null)return BadRequest(Invalid Request);//这儿是验证Token的代码var handler new JwtSecurityTokenHandler();try{ClaimsPrincipal claim handler.ValidateToken(request.Token, new TokenValidationParameters{ValidateIssuerSigningKey true,IssuerSigningKey new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_tokenParameter.Secret)),ValidateIssuer false,ValidateAudience false,ValidateLifetime false,}, out SecurityToken securityToken);var username claim.Identity.Name;//这儿是生成Token的代码var token GenUserToken(username, testUser);var refreshToken 654321;return Ok(new[] { token, refreshToken });}catch(Exception){return BadRequest(Invalid Request);}
}
这样Token刷新就完成了。可以用生成Token运行测试能正常认证通过。 单独说一下refreshTokenrefreshToken名义上是为了刷新Token实际上用处主要是给用户重新登录做计时。refreshToken过期了用户就必须重新登录。就是这么个作用。要不然Token自己刷新岂不更好refreshToken可以采用跟Token一样的生成方式。但是我们也看到Token生成出来的串就很长如果refreshToken也那样生成那就也会是一个很长的串。这样会加大前端到API的传输量。因此这不算是一个好主意。一般来说refreshToken会换一种生成方式。唯一序列、Hash都是可以选择的可以减少很多传输。至于持久化和过期依托数据库就好了。七、彩蛋最后送大家一个彩蛋。在生成Token时我们把过期时间设置成少于五分钟的时长比方3分钟。但这时实测会发现Token的过期失效了。为什么呢TokenValidationParameters有一个属性叫ClockSkew这个参数有个默认值是TimeSpan.FromMinutes(5)。这个参数的意义是考虑到各个服务器之间的时间不一定完全同步系统给了个5分钟的误差时间。这个误差时间导致的结果是少于五分钟的过期时间会在实际认证检查时被忽略。这个情况Microsoft上有N多人在讨论可以自己去查。所以当Token的过期小于5分钟时想要让认证对这个时间生效可以把这个值设为TimeSpan.Zero。option.TokenValidationParameters new TokenValidationParameters
{ValidateIssuerSigningKey true,IssuerSigningKey new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.Secret)),ValidIssuer token.Issuer,ValidateIssuer true,ValidateAudience false,ClockSkew TimeSpan.Zero, //就是这一行
};
我把上面的代码传到了Github上需要了可以拉下来直接测试。代码地址https://github.com/humornif/Demo-Code/tree/master/0007/demo全文完点「在看」让更多人因你而受益↘ ↘ ↘