在Startup.cs的ConfigureServices方法中,使用AddAuthorization方法并在其中定义策略。在这里,我们可以将JWT的“scp”声明视为角色,同时将其转换为以“role:”开头的标准角色声明。我们可以定义一个自定义授权策略,通过读取“roles”声明并将其转换为标准角色声明来实现此目的。
代码示例:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddJwtBearer(options =>
{
// JWT 配置
});
services.AddAuthorization(options =>
{
options.AddPolicy("PolicyName", policy =>
{
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
policy.RequireClaim("scp");
policy.ForwardDefaultSelector = context =>
{
if (context.Request.Headers.ContainsKey("Authorization"))
{
string header = context.Request.Headers["Authorization"];
if (header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
{
return JwtBearerDefaults.AuthenticationScheme;
}
else if (header.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
{
return BasicAuthenticationDefaults.AuthenticationScheme;
}
}
return null;
};
policy.Requirements.Add(new RoleRequirement());
});
});
services.AddSingleton();
}
public class RoleRequirementHandler : AuthorizationHandler
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "scp"))
{
var scopes = context.User.FindFirst(c => c.Type == "scp").Value.Split(' ');
foreach (string scope in scopes)
{
if (scope.StartsWith("role:"))
{
var role = scope.Substring(5);
context.User.AddIdentity(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Role, role) }));
}
}
}
if (context.User.IsInRole(requirement.Role))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class RoleRequirement : IAuthorizationRequirement
{
public RoleRequirement() { }
public string Role { get; set; }
}