Ошибка создания пользовательского AuthorizeAttribute после OnAuthorization

Я хочу сделать кастом AuthorizeAttribute, Я хочу использовать IMemoryCache для хранения токенов, и я использую пользовательский поставщик для внедрения экземпляра IMemoryCache. Моя проблема после OnAuthorization метод, который не называется действием моего контроллера, и он выдает внутреннюю ошибку сервера, которую я не могу отловить.

И вот реализация до сих пор

public class ApiAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public IMemoryCache Cache { get; set; }

    /// <summary>
    /// Verifica se o token é válido na sessão
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        //Check we have a valid HttpContext
        if (context.HttpContext == null)
            throw new ArgumentNullException("httpContext");

        string token;

        token = context.HttpContext.Request.QueryString.Value;
        if (String.IsNullOrEmpty(token))
            token = context.HttpContext.Request.Form["token"];

        if (String.IsNullOrEmpty(token))
        {
            context.Result = new UnauthorizedResult();
            return;
        }

        if (Cache == null)
        {
            context.Result = new UnauthorizedResult();
            return;
        }

        if (token.Contains("="))
        {
            token = token.Split('=')[1];
        }

        var tokens = Cache.Get<Dictionary<string, User>>("tokens");
        var result = (from t in tokens where t.Key == token select t.Value).ToList();

        var controller = (string)context.RouteData.Values["controller"];
        var action = (string)context.RouteData.Values["action"];

        if (result.Count < 1)
            context.Result = new UnauthorizedResult();

    }

}



    public class CacheProvider : IApplicationModelProvider
{
    private IMemoryCache _cache;

    public CacheProvider(IMemoryCache cache)
    {
        _cache = cache;
    }
    public int Order { get { return -1000 + 10; } }

    public void OnProvidersExecuted(ApplicationModelProviderContext context)
    {
        foreach (var controllerModel in context.Result.Controllers)
        {
            // pass the depencency to controller attibutes
            controllerModel.Attributes
                .OfType<ApiAuthorizeAttribute>().ToList()
                .ForEach(a => a.Cache = _cache);

            // pass the dependency to action attributes
            controllerModel.Actions.SelectMany(a => a.Attributes)
                .OfType<ApiAuthorizeAttribute>().ToList()
                .ForEach(a => a.Cache = _cache);
        }
    }

    public void OnProvidersExecuting(ApplicationModelProviderContext context)
    {
        // intentionally empty
    }
}

А вот и контроллер

    [ApiAuthorize]
    [HttpPost]
    public JsonResult Delete([FromForm] string inputId)
    {
        //Do stuff
    }

Заранее спасибо

1 ответ

После некоторых раскопок я нашел этот способ сделать это, я не знаю, является ли это лучшим способом для достижения этого

Я создал требование политики

public class TokenRequirement :  IAuthorizationRequirement
{

}

И AuthorizationHandler

    public class TokenRequirementHandler : AuthorizationHandler<TokenRequirement>
{
    public IMemoryCache Cache { get; set; }

    public TokenRequirementHandler(IMemoryCache memoryCache)
    {
        Cache = memoryCache;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TokenRequirement requirement)
    {
        return Task.Run(() => { //access the cache and then
        context.Succeed(requirement); });
    }
}

На моем стартапе я зарегистрировал обработчик и добавил Авторизацию

        services.AddAuthorization(options =>
        {
            options.AddPolicy("Token",
                policy => policy.Requirements.Add(new Authorize.TokenRequirement()));
        });


        services.AddSingleton<IAuthorizationHandler, Authorize.TokenRequirementHandler>();

В контроллере я использовал Authorize атрибут

    [Authorize(Policy = "Token")]
    [HttpPost]
    public JsonResult Delete([FromForm] string inputId)
    {
       //Do stuff
    }

И теперь это работает. Спасибо.

Другие вопросы по тегам