ASP.NET 5 标识 - 刷新用户的角色



ASP.NET 5中,假设我有以下控制器:

[Route("api/[controller]")]
[Authorize(Roles = "Super")]
public class ValuesController : Controller
{
    // GET: api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new[] { "value1", "value2" };
    }
}

然后假设我有一个用户 Jack,他已登录,但不是超级角色的成员。

当 Jack 尝试访问此资源时,他的访问被拒绝,正如预期的那样。

然后,在另一台机器上,我使用用户管理器将他添加到超级角色。

当 Jack 再次尝试访问此资源时,在他注销并重新登录之前,它仍会被拒绝访问。

如何确保每个用户的角色未缓存,或者在进行更改时以某种方式刷新?

所以这就是我最终设法解决这个问题的方法,但实际上这应该用安全印章来解决。下面的解决方案至少在授权发生之前提供了"查看"。

我创建了一个新AuthorizationHandler,它在其构造函数中接受UserManager

public class SuperRequirement : AuthorizationHandler<SuperRequirement>, IAuthorizationRequirement
{
    public UserManager<ApplicationUser> UserManager { get; set; }
    public SuperRequirement(UserManager<ApplicationUser> userManager)
    {
        UserManager = userManager;
    }
    protected override void Handle(AuthorizationContext context, SuperRequirement requirement)
    {
        throw new System.NotImplementedException();
    }
    protected override async Task HandleAsync(AuthorizationContext context, SuperRequirement requirement)
    {
        var userName = context.User.Identity.Name;
        var pass = await UserManager.IsInRoleAsync(await UserManager.FindByNameAsync(userName), "Super");
        if (pass)
        {
            context.Succeed(requirement);
        }
        else
        {
            context.Fail();
        }
    }
}

然后我在Startup.cs中配置了这个:

public void ConfigureServices(IServiceCollection services)
{
    ...
    var sp = services.BuildServiceProvider();
    //var service = sp.GetService<ISomeService>();
    services.AddAuthorization(options =>
    {
        options.AddPolicy("Super",
            policy =>
            {
                var userManager = sp.GetService<UserManager<ApplicationUser>>();
                policy.Requirements.Add(new SuperRequirement(userManager));
            });
    });
}

最后,我更新了控制器以使用新的授权策略:

[Route("api/[controller]")]
[Authorize(Policy = "Super")]
public class ValuesController : Controller
{
    // GET: api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new[] { "value1", "value2" };
    }
}

通过这种方式,它会检查数据库的每个请求以确保角色对齐,并使用UserManager执行此操作。

请注意,这效率较低,因为每个 API 请求现在都会触发对数据库的额外调用,因此您应该实现某种缓存和失效机制;这只是为了演示原理。

最新更新