You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:50:41