引用:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
我用的是6.几版本的
1.首先创建一个生成Token的类:
public interface IHsOrRssJwtService
{
TokenModel GetToken(SelectBaseReq req);
}
public class HsOrRssJwtService : IHsOrRssJwtService
{
private JWTTokenOptions _jWTTokenOptions;
public HsOrRssJwtService(IOptionsMonitor<JWTTokenOptions> jWTTokenOptions)
{
_jWTTokenOptions = jWTTokenOptions.CurrentValue;
}
public TokenModel GetToken(SelectBaseReq req)
{
//这里可以自定义想写多少写多少
var claim = new[] {
new Claim("ID",“1111”),
new Claim("WXPolicy",“222”),
new Claim("UserName",“333”),
new Claim("Code",“666”)
};
//使用对称加密
SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jWTTokenOptions.SecurityKey)) ;
SigningCredentials credentials = new SigningCredentials(key,SecurityAlgorithms.HmacSha256);
JwtSecurityToken token = new JwtSecurityToken(
issuer: _jWTTokenOptions.Issuer,
audience: _jWTTokenOptions.Audience,
claims:claim,
expires:DateTime.Now.AddHours(8),//有效期
signingCredentials:credentials
);
string tokenstr=new JwtSecurityTokenHandler().WriteToken(token);
TokenModel model= new TokenModel();
model.token= tokenstr;
return model;
}
}
定义JWT的类
public class JWTTokenOptions
{
/// <summary>
/// 订阅者
/// </summary>
public string? Audience { get; set; }
/// <summary>
/// 密钥
/// </summary>
public string? SecurityKey { get; set; }
//发行者
public string? Issuer { get; set; }
}
2.appsettings.json中增加配置
"JWTTokenOptions": {
"SecurityKey": "jsaduwqe6asdjewejdue7dfmsdfu0sdfmwmsd8wfsd6",
//"Audience": "https://localhost:7222",
//"Issuer": "https://localhost:7222"
"Audience": "99999",
"Issuer": "888888"
}
3.Program.cs中注入
builder.Services.Configure<JWTTokenOptions>(builder.Configuration.GetSection("JWTTokenOptions"));
builder.Services.AddTransient<IHsOrRssJwtService, HsOrRssJwtService>();
在Swagger中增加token验证
builder.Services.AddSwaggerGen(options =>
{
foreach (FieldInfo fileld in typeof(ApiVersionInfo).GetFields())
{
options.SwaggerDoc(fileld.Name, new OpenApiInfo
{
Version = fileld.Name,
Title = "API标题",
Description = $"API描述,{fileld.Name}版本"
});
}
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Description = "在下框中输入请求头中需要添加Jwt授权Token:Bearer Token",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
BearerFormat = "JWT",
Scheme = "Bearer"
}
);
options.AddSecurityRequirement(new OpenApiSecurityRequirement {
{ new OpenApiSecurityScheme {
Reference = new OpenApiReference
{ Type = ReferenceType.SecurityScheme, Id = "Bearer" }
}, new string[] { }
} });
});
增加认证
#region JWT HS
JWTTokenOptions jWTTokenOptions = new JWTTokenOptions();
builder.Configuration.Bind("JWTTokenOptions", jWTTokenOptions);
string aa = jWTTokenOptions.SecurityKey;
builder.Services.AddAuthentication(p =>
{
p.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
p.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(p =>
{
p.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否验证发行者
ValidateAudience = true,//是否验证订阅者
ValidateLifetime = true,//是否验证有效期
ValidateIssuerSigningKey = true,//是否验证发密钥
ValidAudience = jWTTokenOptions.Audience,//蛇者订阅者
ValidIssuer = jWTTokenOptions.Issuer,//设置发行者
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jWTTokenOptions.SecurityKey)),//设置密钥
};
});
#endregion
开启认证授权
app.UseSwagger();
app.UseSwaggerUI(c =>
{
foreach (FieldInfo field in typeof(ApiVersionInfo).GetFields())
{
c.SwaggerEndpoint($"/swagger/{field.Name}/swagger.json", $"{field.Name}");
}
});
app.UseAuthentication();
app.UseAuthorization();
最后创建一个API 就可以生成token了
[ApiController]
[Route("api/[controller]")]
[ApiExplorerSettings(GroupName = nameof(ApiVersionInfo.V1))]
public class TokenController : ControllerBase
{
private IHsOrRssJwtService _hsOrRssJwtService;
public TokenController(IHsOrRssJwtService hsOrRssJwtService)
{
_hsOrRssJwtService=hsOrRssJwtService;
}
[HttpPost("GetToken")]
public TokenModel GetToken(SelectBaseReq req)
{
return _hsOrRssJwtService.GetToken(req);
}
[HttpPost("GetData")]
[Authorize(Policy= "WXPolicy")]
public string GetData( )
{
return "123712432";
}
}
4.在需要授权的方法或者控制器上增加[Authorize] 就可以控制是否需要token验证了
[HttpPost("GetData")]
[Authorize(Policy= "WXPolicy")]
public string GetData( )
{
return "123712432";
}
注意这个(Policy= "WXPolicy") 就是策略认证
先添加一个JwtAuthorizationRequirement 并继承IAuthorizationRequirement
public class JwtAuthorizationRequirement: IAuthorizationRequirement
{
//这里可以扩展一些其他的角色或者需要的东西
public JwtAuthorizationRequirement(string txt)
{
Name = txt;
}
public string? Name { get; set; }
}
然后创建一个JwtAuthorizationHandler并继承 AuthorizationHandler<JwtAuthorizationRequirement>
public class JwtAuthorizationHandler : AuthorizationHandler<JwtAuthorizationRequirement>
{
private readonly IJwtUserCheck _jwtUserCheck;
public JwtAuthorizationHandler(IJwtUserCheck jwtUserCheck)
{
_jwtUserCheck = jwtUserCheck;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, JwtAuthorizationRequirement requirement)
{
if (context.User == null)
{
context.Fail();
return Task.CompletedTask;
}
//requirement.Name 就是在添加策略授权时传入的值 ,这句查询需要在颁发token时添加也可以不添加看个人需求
string Name = context.User.Claims.FirstOrDefault(p => p.Type == requirement.Name)?.Value;
string ID = context.User.Claims.FirstOrDefault(p => p.Type == "ID")?.Value;
string Code = context.User.Claims.FirstOrDefault(p => p.Type == "Code")?.Value;
//打印
foreach (var claim in context.User.Claims)
{
Console.WriteLine($"{claim.Type}:{claim.Value}");
}
UserDto model = new UserDto();
model.ID = ID;
model.Code = Code;
//这里时数据库校验
if (!_jwtUserCheck.CheckLogin(model))
{
context.Fail();
}
else {
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
注意 context.Succeed();这个 验证成功时一定要加
然后再Program.cs中添加授权验证
builder.Services.AddAuthorization(p =>
{
p.AddPolicy("WXPolicy", t =>
{
t.Requirements.Add(new JwtAuthorizationRequirement("WXPolicy"));
});
});