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

Asp.Net Core Web API 5.0与Angular自定义角色授权实现咨询

实现角色授权校验的方案

你可以直接用ASP.NET Core自带的自定义授权中间件+自定义属性的方案实现,完全不需要依赖Asp.Net Identity,具体步骤如下:

步骤1:定义角色校验标注属性

先定义一个自定义属性,用来标记哪些控制器/动作方法需要做角色校验、以及需要的角色权限:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequiresRoleAttribute : Attribute
{
    // 允许传入多个要求的角色,用户拥有任意一个即可访问
    public string[] RequiredRoles { get; }
    public RequiresRoleAttribute(params string[] requiredRoles)
    {
        RequiredRoles = requiredRoles;
    }
}

步骤2:实现全局授权中间件

中间件会在所有请求进入控制器之前统一处理鉴权逻辑,不用在每个动作方法里重复写校验代码:

public class CustomRoleAuthMiddleware
{
    private readonly RequestDelegate _next;

    public CustomRoleAuthMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, YourDbContext dbContext, IDistributedCache cache)
    {
        // 获取当前请求对应的终点元数据
        var endpoint = context.GetEndpoint();
        if (endpoint == null)
        {
            await _next(context);
            return;
        }

        // 检查当前请求的控制器/动作是否需要角色校验
        var roleAuthAttr = endpoint.Metadata.GetMetadata<RequiresRoleAttribute>();
        if (roleAuthAttr == null)
        {
            // 无校验要求直接放行
            await _next(context);
            return;
        }

        // 从请求头取前端传递的UserID,Header名可以和前端自行约定
        if (!context.Request.Headers.TryGetValue("X-User-ID", out var userIdStr) || !Guid.TryParse(userIdStr, out var userId))
        {
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            return;
        }

        // 先查缓存获取用户角色,避免频繁查库
        var cacheKey = $"user_roles_{userId}";
        var cachedRoles = await cache.GetStringAsync(cacheKey);
        List<string> userRoles;

        if (!string.IsNullOrEmpty(cachedRoles))
        {
            userRoles = JsonSerializer.Deserialize<List<string>>(cachedRoles);
        }
        else
        {
            // 缓存不存在时从存量UserRole表查询用户所有角色
            userRoles = await dbContext.UserRoles
                .Where(ur => ur.UserId == userId)
                .Select(ur => ur.RoleName)
                .ToListAsync();

            // 查询结果写入缓存,过期时间可根据业务调整,比如15分钟
            await cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(userRoles), new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)
            });
        }

        // 校验用户是否拥有要求的角色
        if (!roleAuthAttr.RequiredRoles.Intersect(userRoles).Any())
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;
            return;
        }

        // 校验通过放行
        await _next(context);
    }
}

步骤3:注册中间件到请求管道

在Program.cs中注册中间件,注意要放在路由匹配之后、控制器执行之前:

// 其他服务注册、中间件配置省略
app.UseRouting();
// 注册自定义角色授权中间件
app.UseMiddleware<CustomRoleAuthMiddleware>();
app.MapControllers();
// 其他配置省略

步骤4:给需要鉴权的接口加标注

// 作用在控制器上,整个控制器所有接口都需要Admin角色
[RequiresRole("Admin")]
public class SystemConfigController : ControllerBase
{
    // 作用在单独动作上,覆盖控制器的配置,支持同时指定多个角色
    [RequiresRole("Admin", "Auditor")]
    public IActionResult GetAuditLogs()
    {
        return Ok();
    }
}

关于是否需要每个动作都查库的问题

完全不需要在每个动作方法里单独查询数据库:

  • 中间件已经统一处理了全局所有请求的角色校验逻辑,业务代码里不需要再重复写鉴权代码
  • 配合缓存机制可以大幅降低数据库查询压力,只有缓存过期、或者用户角色变动时才需要重新查询数据库。如果用户角色发生变更,你只需要在修改角色的业务逻辑里删除对应用户的角色缓存即可。

内容的提问来源于stack exchange,提问作者Dibyo Chatterjee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:09:03