今天尝试 jwt 验证签名,总是报401,百思不得其解
这是创建token 方法
public static string GenerateJwt(IEnumerable<string> userRoles, JwtTokenPayload payload)
{
var claims = new List<Claim>
{
new Claim(JwtClaimKey.UserId, payload.UserId),
new Claim(JwtClaimKey.UserName, payload.UserName),
new Claim(JwtRegisteredClaimNames.Iss,Iss),
new Claim(JwtRegisteredClaimNames.Aud,Aud),
new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddHours(2)).ToUnixTimeSeconds()}"),
};
// 可以将一个用户的多个角色全部赋予,比如参数System,Admin,那么该token即拥有两个角色
claims.AddRange(userRoles.Select(role => new Claim(ClaimTypes.Role, role)));
//秘钥 (SymmetricSecurityKey 对安全性的要求,密钥的长度太短会报出异常)
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var jwt = new JwtSecurityToken(
issuer: Iss,
audience: Aud,
claims: claims,
expires: DateTime.Now.AddHours(Expire),
signingCredentials: credentials);
var jwtHandler = new JwtSecurityTokenHandler();
var encodedJwt = jwtHandler.WriteToken(jwt);
return encodedJwt;
}
注册授权
services.AddAuthentication(options =>
{
// 设置默认使用jwt验证方式
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
// 添加JwtBearer服务
.AddJwtBearer(o =>
{
// token验证参数
o.TokenValidationParameters = new TokenValidationParameters
{
// 验证秘钥
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SetAppConfig.SecretKey)),
// 验证颁发者
ValidateIssuer = true,
ValidIssuer = SetAppConfig.Issuer,
// 验证订阅者
ValidateAudience = true,
ValidAudience = SetAppConfig.Audience,
////验证令牌过期时间
ValidateLifetime = true,
// 验证过期时间必须设置该属性
ClockSkew = TimeSpan.FromDays(1)
};
// 默认有www-authenticate响应头提示验证失败信息
});
// 如果需要角色控制到Action则需要配置Policy
// 如果没有配置AddPolicy,接口直接使用[Authorize]特性即可
// 如果接口只允许Admin或System角色的Token访问,则需要添加了[Authorize("SystemOrAdmin")]特性
// 详细请测试LoginController的ParseToken的方法
services.AddAuthorization(options =>
{
//自定义策略(用于角色路径验证)
//options.AddPolicy("Permission", policy => policy.Requirements.Add(new PolicyRequirement()));
options.AddPolicy("User", policy => policy.RequireRole("User"));
//options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
});
然后是在ConfigureServices中 添加 AddSwaggerGen方法中与swaager绑定
s.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
Name = "Authorization",//jwt默认的参数名称
In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
Type = SecuritySchemeType.ApiKey,
Scheme = "bearer"
});
//声明一个Scheme,注意下面的Id要和上面AddSecurityDefinition中的参数name一致
var scheme = new OpenApiSecurityScheme()
{
Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
};
//注册全局认证(所有的接口都可以使用认证)
s.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
[scheme] = new string[0]
});