如何在ASP.NET Core Web API中实现基于角色的授权?
ASP.NET Core Web API 基于角色授权分步实现指南
1. 安装基础依赖
先安装JWT认证所需的NuGet包:
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
2. 配置认证与授权中间件(Program.cs)
在Program.cs中完成JWT认证配置,这是前后端分离场景的标准方案:
var builder = WebApplication.CreateBuilder(args); // 配置JWT认证服务 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; }); // 启用授权服务 builder.Services.AddAuthorization(); var app = builder.Build(); // 注意中间件顺序:先执行认证,再执行授权 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
3. 登录接口注入角色声明
在登录接口验证用户身份后,生成JWT时将用户角色添加到Claims集合中:
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly IConfiguration _config; public AuthController(IConfiguration config) { _config = config; } [HttpPost("login")] public IActionResult Login([FromBody] LoginModel model) { // 替换为你的数据库用户验证逻辑 var user = ValidateUser(model.Username, model.Password); if (user == null) { return Unauthorized("无效的登录凭据"); } // 生成包含用户角色的Claims var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.Username), new Claim(ClaimTypes.Role, user.Role) // 角色为sysAdmin/employee/patient中的一个 }; // 生成JWT令牌 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: _config["Jwt:Issuer"], audience: _config["Jwt:Audience"], claims: claims, expires: DateTime.Now.AddHours(1), signingCredentials: creds); return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token), role = user.Role }); } // 模拟用户验证方法,实际项目从数据库查询 private UserModel ValidateUser(string username, string password) { if (username == "admin" && password == "admin123") { return new UserModel { Username = "admin", Role = "sysAdmin" }; } if (username == "staff" && password == "staff123") { return new UserModel { Username = "staff", Role = "employee" }; } if (username == "patient01" && password == "patient123") { return new UserModel { Username = "patient01", Role = "patient" }; } return null; } } // 辅助模型 public class LoginModel { public string Username { get; set; } public string Password { get; set; } } public class UserModel { public string Username { get; set; } public string Role { get; set; } }
4. 给API接口添加角色授权
方式1:直接指定角色(快速简单)
[ApiController] [Route("api/users")] [Authorize(Roles = "sysAdmin")] // 整个控制器仅sysAdmin可访问 public class UsersController : ControllerBase { // 仅sysAdmin可调用 [HttpGet] public IActionResult GetAllUsers() { return Ok(new List<string> { "user1", "user2", "user3" }); } // sysAdmin和employee均可调用 [HttpGet("{id}")] [Authorize(Roles = "sysAdmin,employee")] public IActionResult GetUser(int id) { return Ok($"用户详情:{id}"); } }
方式2:使用授权策略(灵活适配复杂场景)
先在Program.cs中定义策略:
builder.Services.AddAuthorization(options => { options.AddPolicy("RequireSysAdmin", policy => policy.RequireRole("sysAdmin")); options.AddPolicy("RequireStaff", policy => policy.RequireRole("sysAdmin", "employee")); options.AddPolicy("RequirePatient", policy => policy.RequireRole("patient")); });
然后在控制器/方法上绑定策略:
[ApiController] [Route("api/patients")] [Authorize(Policy = "RequirePatient")] public class PatientsController : ControllerBase { [HttpGet("my-profile")] public IActionResult GetMyProfile() { return Ok("患者个人健康档案"); } }
5. 自定义未授权响应
默认情况下,无权限访问会返回403状态码,可通过JWT事件自定义响应内容:
.AddJwtBearer(options => { // 其他配置... options.Events = new JwtBearerEvents { OnForbidden = context => { context.Response.StatusCode = StatusCodes.Status403Forbidden; context.Response.ContentType = "application/json"; return context.Response.WriteAsync(JsonSerializer.Serialize(new { code = 403, message = "您没有权限访问该资源" })); }, OnUnauthorized = context => { context.Response.StatusCode = StatusCodes.Status401Unauthorized; context.Response.ContentType = "application/json"; return context.Response.WriteAsync(JsonSerializer.Serialize(new { code = 401, message = "认证过期,请重新登录" })); } }; });
6. 配合前端控制内容显示
- 后端提供获取当前用户信息的接口,返回角色:
[ApiController] [Route("api/auth")] [Authorize] public class AuthController : ControllerBase { [HttpGet("current-user")] public IActionResult GetCurrentUser() { var username = User.Identity.Name; var role = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value; return Ok(new { username, role }); } }
- Angular端登录后调用该接口,存储用户角色,通过
*ngIf="currentUser.role === 'sysAdmin'"等指令控制UI元素显示/隐藏。注意:前端隐藏仅为体验优化,后端的授权校验才是安全核心,所有敏感接口必须添加授权注解。
内容的提问来源于stack exchange,提问作者Milos
相关产品推荐
相关产品推荐

