Как фильтровать в webApi по ролям - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть этот контроллер

public class WorkController : ControllerBase
{
    [Authorize(Roles = "admin")]
    [HttpPost("something/add")]
    public async Task<IActionResult> Add()
    {
        //add
    }
    [Authorize(Roles = "admin,support")]
    [HttpGet("something/get")]
    public async Task<IActionResult> Get()
    {
        //get
    }
}

авторизация работает нормально, но я думаю, что она могла бы быть лучше, я просто хочу спросить, есть ли что-то вроде того, что я могу отфильтровать Роли и разрешить его на основе глагола http, например, если роль отправителя admin , он может получить доступ ко всем методам, а если роль support , он может получить доступ только к Get методы. Сделать это глобально было бы здорово, так как у меня много методов

1 Ответ

1 голос
/ 25 февраля 2020

Я просто хочу спросить, могу ли я отфильтровать роли и разрешить это на основе глагола http, например, если роль отправителя - admin, он может получить доступ ко всем методам, и если роль поддерживается Он мог получить доступ только к методам Get.

Конечно. Во-первых, вам нужно создать правила:

public class GlobalVerbRoleRequirement: IAuthorizationRequirement
{
    public bool IsAllowed(string role, string verb)
    {
        // allow all verbs if user is "admin"
        if(string.Equals("admin", role, StringComparison.OrdinalIgnoreCase)) return true;
        // allow the "GET" verb if user is "support"
        if(string.Equals("support", role, StringComparison.OrdinalIgnoreCase) && string.Equals("GET",verb, StringComparison.OrdinalIgnoreCase)){
            return true;
        };
        // ... add other rules as you like
        return false;
    }
}

(Вы можете настроить IsAllowed(role, verb) дальше, если у вас есть больше правил)

И сказать ASP. NET Основные способы обработки этих правил с AuthorizationHandler:

public class GlobalVerbRoleHandler : AuthorizationHandler<GlobalVerbRoleRequirement>
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public GlobalVerbRoleHandler(IHttpContextAccessor httpContextAccessor)
    {
        this._httpContextAccessor = httpContextAccessor;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GlobalVerbRoleRequirement requirement)
    {
        // check whether the user has required roles for current verb
        var roles = context.User.FindAll(c => string.Equals(c.Type,ClaimTypes.Role)).Select(c => c.Value);
        var verb= _httpContextAccessor.HttpContext?.Request.Method;
        if(string.IsNullOrEmpty(verb)){ throw new Exception($"request cann't be null!"); }
        foreach(var role in roles){
            if(requirement.IsAllowed(role,verb)){
                context.Succeed(requirement); 
                return Task.CompletedTask;
            }
        }
        context.Fail();
        return Task.CompletedTask;
    }
}

Наконец, не забудьте зарегистрировать соответствующие службы при запуске:

services.AddHttpContextAccessor();
services.AddScoped<IAuthorizationHandler, GlobalVerbRoleHandler>();
services.AddAuthorization(opts =>{
    opts.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddRequirements(new GlobalVerbRoleRequirement())
        .Build();
});

Теперь каждый [Authorize] также будет проверить Роль против текущего HTTP Глагол автоматически.

[Authorize]
public class WorkController : ControllerBase
{

    [HttpPost("something/add")]
    public async Task<IActionResult> Add()
    {
        //add
    }

    [HttpGet("something/get")]
    public async Task<IActionResult> Get()
    {
        //get
    }
}
...