ASP.NET 5 Identity - 刷新用户角色

3
在 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尝试访问此资源时,他会得到预期的访问被拒绝的信息。
然后,我从另一台机器上,使用UserManager将他添加到“超级”角色。
当Jack再次尝试访问此资源时,他仍然无法访问,除非他先退出并重新登录。
我应该如何确保每个用户的角色不被缓存,或者在进行更改时进行刷新?
1个回答

1
所以这是我最终解决这个问题的方法,但实际上应该使用安全印章来解决。以下解决方案至少在授权发生之前提供了“查看”的功能。
我创建了一个新的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请求现在都会触发对数据库的额外调用,因此您应该实现某种缓存和失效机制;这只是为了演示原理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接