jwt实现认证和自定义策略授权
场景
客户端根据用户名和密码访问登录接口获取token,服务端登录接口获取账号和密码进行验证,获取用户的角色,若角色是超级管理员则只能授权访问标记为超级管理员的接口,若角色是管理员则只能授权访问标记为管理员的接口。
实现JWT认证
安装JWT包
Microsoft.AspNetCore.Authentication.JwtBearer
配置JWT信息
"JwtSettings": {
"Issuer": "YourIssuer",
"Audience": "YourAudience",
"SecretKey": "YourSuperSecretKeyThatShouldBeLongAndSecure"
},
创建JWT配置映射实体类
public class JwtSettings
{
public string Issuer { get; set; }
public string Audience { get; set; }
public string SecretKey { get; set; }
}
JWT认证服务配置和添加认证中间件
// 配置 JWT 设置
var jwtSettings = builder.Configuration.GetSection("JwtSettings").Get<JwtSettings>();
// 添加认证服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtSettings.Issuer,
ValidAudience = jwtSettings.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey))
};
options.Events = new JwtBearerEvents
{
OnForbidden = async context =>
{
context.Response.StatusCode = 403;
// await context.Response.WriteAsync("服务端拒绝访问:当前身份没有权限访问,请联系管理员开放权限");
await context.Response.WriteAsJsonAsync(new { message = "服务端拒绝访问:当前身份没有权限访问,请联系管理员开放权限" });
}
};
});
var app = builder.Build();
app.UseAuthentication();
实现自定义策略授权
定义权限策略类
/// <summary>
/// 权限策略类
/// </summary>
public class PermissionRequirement : IAuthorizationRequirement
{
public string _roleName { get; }
public PermissionRequirement(string RoleName)
{
_roleName = RoleName;
}
}
IAuthorizationRequirement 用于定义授权策略中的具体要求。当你需要实现自定义的授权逻辑时,可以创建实现该接口的类,然后将这些类添加到授权策略中。在用户请求访问受保护资源时,授权系统会检查用户是否满足这些要求。
定义策略处理类
public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == requirement._roleName))
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
await Task.CompletedTask;
}
}
AuthorizationHandler 是一个抽象类,位于 Microsoft.AspNetCore.Authorization 命名空间下。它的主要作用是根据特定的授权要求(实现 IAuthorizationRequirement 接口的类)来判断用户是否有权限访问受保护的资源。开发者需要继承 AuthorizationHandler<TRequirement> 泛型类(其中 TRequirement 是具体的授权要求类型),并重写 HandleRequirementAsync 方法来实现自定义的授权逻辑。
配置自定义策略授权和添加授权中间件
// 添加自定义授权策略
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AdminPolicy", policy => policy.Requirements.Add(new PermissionRequirement("Admin")));
options.AddPolicy("SuperAdminPolicy", policy => policy.Requirements.Add(new PermissionRequirement("SuperAdmin")));
});
var app = builder.Build();
app.UseAuthorization(); //注意,授权中间件放在认证中间件后面
依赖注入
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<IAuthorizationHandler, PermissionRequirementHandler>();
实现接口
创建请求实体
public class LoginRequest
{
public string username { get; set; }
public string password { get; set; }
}
创建接口
在管理员和超级管理员接口前加上特性进行区分。
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
private readonly IConfiguration _configuration;
public TestController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpPost("login")]
public IActionResult Login(LoginRequest request)
{
string role = string.Empty;
if (request.username == "a" && request.password == "123456")
{
role = "Admin";
}
else if (request.username == "b" && request.password == "123456")
{
role = "SuperAdmin";
}
var jwtSettings = _configuration.GetSection("JwtSettings").Get<JwtSettings>();
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(jwtSettings.SecretKey);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, request.username),
new Claim(ClaimTypes.Role, role)
}),
Issuer = jwtSettings.Issuer,
Audience = jwtSettings.Audience,
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
string tokenString = tokenHandler.WriteToken(token);
return Ok(new { token = tokenString, message = "登录成功" });
}
[HttpGet("GetAdminUserInformation")]
[Authorize(Policy = "AdminPolicy")]
public IActionResult GetAdminUserInformation()
{
return Ok(new { Name = "管理员", Age = 18, Sex = "男" });
}
[HttpGet("GetSuperAdminInformation")]
[Authorize(Policy = "SuperAdminPolicy")]
public IActionResult GetSuperAdminInformation()
{
return Ok(new { Name = "超级管理员", Age = 19, Sex = "男" });
}
}
请求测试
用管理员账号访问管理员接口ok,访问超级管理员接口返回403



用超级管理员账号访问超级管理员接口ok,访问管理员接口同样返回403



人生如逆旅
我亦是行人

浙公网安备 33010602011771号