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

修改AspNetUser.IsEnabled为False后[Authorize]未失效?求解答

ASP.NET Core Identity禁用用户/角色变更后仍可访问的问题

这是正常的默认行为。ASP.NET Core Identity默认会把用户的身份信息(包括启用状态、角色列表等)序列化到身份验证Cookie里,后续请求只会验证Cookie的合法性(比如是否过期、签名是否有效),不会每次都去数据库拉取用户的实时状态。所以哪怕你在数据库里把IsEnabled改成false,只要用户的Cookie还没失效,照样能通过[Authorize]的校验,角色变更的问题也是同理。

解决方法

1. 全局实时校验用户状态与角色

通过实现IClaimsTransformation接口,每次请求时从数据库同步用户的最新状态,更新身份Claims:

public class CustomClaimsTransformer : IClaimsTransformation
{
    private readonly UserManager<IdentityUser> _userManager;

    public CustomClaimsTransformer(UserManager<IdentityUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var identity = principal.Identity as ClaimsIdentity;
        var userId = identity?.FindFirstValue(ClaimTypes.NameIdentifier);
        if (userId == null) return principal;

        var user = await _userManager.FindByIdAsync(userId);
        // 用户不存在或已禁用,直接返回空身份,触发未授权
        if (user == null || !user.IsEnabled)
            return new ClaimsPrincipal(new ClaimsIdentity());

        // 同步角色Claims
        var currentRoles = identity.FindAll(ClaimTypes.Role).Select(c => c.Value);
        var dbRoles = await _userManager.GetRolesAsync(user);

        // 添加新增的角色
        foreach (var role in dbRoles.Except(currentRoles))
            identity.AddClaim(new Claim(ClaimTypes.Role, role));

        // 移除已取消的角色
        foreach (var role in currentRoles.Except(dbRoles))
        {
            var claim = identity.FindFirst(c => c.Type == ClaimTypes.Role && c.Value == role);
            if (claim != null) identity.RemoveClaim(claim);
        }

        return principal;
    }
}

在Program.cs中注册这个服务:

builder.Services.AddScoped<IClaimsTransformation, CustomClaimsTransformer>();

注意:这种方式会给每个请求增加一次数据库查询,高并发场景下需要考虑性能影响。

2. 自定义授权策略,按需校验

创建专属的授权要求和处理程序,只在需要的地方校验用户启用状态:

// 定义授权要求
public class UserEnabledRequirement : IAuthorizationRequirement { }

// 实现授权处理逻辑
public class UserEnabledHandler : AuthorizationHandler<UserEnabledRequirement>
{
    private readonly UserManager<IdentityUser> _userManager;

    public UserEnabledHandler(UserManager<IdentityUser> userManager)
    {
        _userManager = userManager;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, UserEnabledRequirement requirement)
    {
        var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
        if (userId == null)
        {
            context.Fail();
            return;
        }

        var user = await _userManager.FindByIdAsync(userId);
        if (user != null && user.IsEnabled)
            context.Succeed(requirement);
        else
            context.Fail();
    }
}

注册授权服务和策略:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireEnabledUser", policy =>
        policy.Requirements.Add(new UserEnabledRequirement()));
});
builder.Services.AddScoped<IAuthorizationHandler, UserEnabledHandler>();

然后在控制器/Action上使用这个策略:

[Authorize(Policy = "RequireEnabledUser")]
public IActionResult RestrictedAction()
{
    return View();
}

这种方式更灵活,只对指定的接口生效,不会全局增加数据库开销。

3. 修改用户状态后主动刷新身份

当你在后台修改了用户的IsEnabled或角色后,调用SignInManager的刷新方法更新用户Cookie:

await _signInManager.RefreshSignInAsync(targetUser);

这个方法会重新生成包含最新信息的Cookie,用户下次请求就会使用新的身份数据。但它只能在用户当前在线且操作后台时触发,无法主动强制所有已登录用户刷新,适合后台操作后即时生效的场景。

4. 缩短Cookie有效期(折中方案)

如果对实时性要求不高,可以缩短Cookie的过期时间,让用户更快重新登录以获取最新状态:

builder.Services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
    options.SlidingExpiration = true; // 用户活动时自动延长有效期
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:47:15