环境:.net core 5
项目类型:WebApi
目标:使用Jwt为项目做身份验证,为了前后端分离开发时保护接口安全。
---------------------------------------------------------------------------------------------------------------------------------------------
第一步:
在Startup.cs文件的ConfigureServices方法中注册JWT身份验证服务
services.AddAuthentication(option => { option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; //jwt Bearer默认值 option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; });
然后在Configure中启用身份验证
app.UseAuthentication();
注意:需要在app.UseAuthorization();之前启用身份验证,因为需要进行身份验证后才能进行授权。
第二步:
我们需要为JWT配置它所承载的方法,比如我们需要验证的参数,既然是身份验证肯定需要验证参数,和一些事件等,比如身份验证不通过时等,那我们第二步开始给JWT配置验证参数。
1 services.AddAuthentication(option => 2 { 3 option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; //jwt Bearer默认值 4 option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 5 }).AddJwtBearer(option => { 6 option.TokenValidationParameters = new TokenValidationParameters 7 { 8 //是否验证签发者 9 ValidateIssuer = true, 10 //签发者 11 ValidIssuer = "jiaheshangqianfa", 12 //是否验证接受者 13 ValidateAudience = true, 14 //接受者 15 ValidAudience = "jiaheshangjieshou", 16 //是否验证签名密钥 17 ValidateIssuerSigningKey = true, 18 //签名密钥 19 IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("chuangqianmingyueguang")), 20 ////验证令牌过期时间 21 ValidateLifetime = true, 22 //令牌安全时是否保存令牌 23 SaveSigninToken = true, 24 //令牌过期时间的偏移值 25 ClockSkew = TimeSpan.FromSeconds(1) 26 }; 27 });
对于签发者和接受者还有签名密钥的参数,在实际开发中,为了方便维护,肯定是写在配置文件中,这里为了方便理解,就直接赋值了。
JWT的签名密钥长度需要符合HS256的规定否则会报错。
注意:ClockSkew默认时间为5分钟,如你设置令牌过期时间为5分钟,那么验证范围在10分钟内,这是一个大坑!!!!!!!!!!!!
第三步:当我们已经可以对JWT令牌进行验证了,那么接下来肯定就是构造我们的JWT令牌了。
1.创建一个JwtManager,来管理我们的JWT令牌。
using Microsoft.IdentityModel.Tokens; using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; namespace JWTDemo { public class JwtManager { public string CreatJwtToken() { //签名密钥 string jwtKey = "chuangqianmingyueguang"; //签发者 string jwtIssuser = "jiaheshangqianfa"; //接收者 string jwtAudience = "jiaheshangjieshou"; //令牌所承载的信息 var claims = new[] { //用户Id new Claim("Id","userId"), new Claim("Name","userName"), new Claim("Role","userRole") }; //获取对称密钥 var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(jwtKey)); //使用has256加密密钥 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //生成token var token = new JwtSecurityToken( //签发者 jwtIssuser, //接收者 jwtAudience, //jwt令牌数据体 claims: claims, //令牌过期时间 expires: DateTime.Now.AddMinutes(10), //为数字签名定义SecurityKey signingCredentials: creds ); return "Bearer " + new JwtSecurityTokenHandler().WriteToken(token); } } }
那么我们现在来试试是否能生成JWT令牌了!
我们在项目默认创建的WeatherForecastController控制器中修改GET请求接口来返回一个Jwt令牌。
[HttpGet] public string Get() { JwtManager jwtManager = new JwtManager(); string jwtToken = jwtManager.CreatJwtToken(); return jwtToken; }
启动项目!!!请求接口!!!
现在我们已经成功拿到JWT令牌,那么我看来看看这个令牌是否正确,复制令牌到Jwt解析看一下(https://jwt.io/ )。
我们需要把令牌的前缀Bearer删掉,因为Bearer前缀是在我们项目中所需要的规范,然后将我们的签名密钥输入到右下角,左下角提示Signature Verified那么我们的令牌验证成功!
我们可以看到Jwt令牌分为 Header Payload VerifySignature 三部分。
Header是表示token的类型(Jwt)和加密方式(HS256)。
Payload是我们在令牌中所承载的用户信息。
VerifySignature是将 Header进行base64加密 + Payload进行64加密 + 签名密钥 组成好后进行HS256加密。
第四步:保护接口
我们现在已经有了Jwt令牌,也有了Jwt验证方案,那么我们怎么对接口进行保护呢,很简单。
示例:
[HttpPost] [Authorize] public string Test() { return "通过!"; }
我们只需要在接口上方加上 [Authorize] 那么这个接口就需要验证令牌访问,我们试试直接访问这个接口。
很显然接口提示 401错误,我们需要进行身份验证,在请求头中加入 Authorization
这里需要对Swagger进行一些配置,使用NuGet安装Swashbuckle.AspNetCore.Filters
此处直接粘Swagger配置代码,因为我们的重点在Jwt。
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWTDemo", Version = "v1" }); c.OperationFilter<SecurityRequirementsOperationFilter>(); c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"", Name = "Authorization",//jwt默认的参数名称 In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); });
启动项目!
我们像之前那样先拿到Jwt的令牌,复制令牌,然后
可以看到这里Swagger有一个小锁,将令牌粘贴进去,访问接口
可以看到我们的接口已经可以访问通过!
附上Demo链接地址:https://gitee.com/lu-qi2166690055/net5-jwt-demo
以上内容均为原创,转载请注明并带上链接,谢谢。