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

时间:2016-01-28 08:24:38

标签: asp.net-identity asp.net-core

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,他已登录但 Super 角色的成员。

当Jack试图访问此资源时,他会按预期拒绝访问。

然后,从另一台机器,我使用UserManager将他添加到 Super 角色。

当Jack再次尝试访问此资源时,它仍会被拒绝访问,直到他退出并重新登录。

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

1 个答案:

答案 0 :(得分: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请求现在都会触发对数据库的额外调用,因此您应该实现某种缓存和失效机制;这只是为了证明这一原则。