Исключение: данный фильтр должен реализовывать один или несколько из следующих интерфейсов фильтра при реализации настраиваемого фильтра в WebAPI 2

Я пытаюсь создать свой настраиваемый фильтр для проверки подлинности, но я запускаю эту проблему, когда пытаюсь запустить решение WebAPI:

Данный экземпляр фильтра должен реализовать одно или несколько из следующих фильтров: System.Web.Mvc.IAuthorizationFilter, System.Web.Mvc.IActionFilter, System.Web.Mvc.IResultFilter, System.Web.Mvc.IExceptionFilter, System.Web.Mvc.Filters.IAuthenticationFilter.

Ошибка в классе FilterConfig:

public class FilterConfig
{
   public static void RegisterGlobalFilters(GlobalFilterCollection filters)
   {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new AuthAttribute());
   }
}

В строке, где я пытаюсь добавить атрибут AuthAttribute для фильтров.

Это целый класс AuthAttribute:

using Examino.Business;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IdentityModel;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace Examino.API.Filters
{
    public class AuthAttribute : AuthorizeAttribute
    {
        public ITokenProviderService TokenProviderService { get; set; }

        public override void OnAuthorization(HttpActionContext actionContext)
        {
            SetDependencies(actionContext);

            if (!IsAuthorized(actionContext) && !SkipAuthorization(actionContext))
            {
                if (Authenticate(actionContext) == AuthenticationErrors.UNAUTHORIZED)
                {
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,
                        new HttpResponseMessage(HttpStatusCode.Unauthorized));
                }
                else if (Authenticate(actionContext) == AuthenticationErrors.TOKEN_EXPIRED)
                {
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,
                        //token expired status code?
                        new HttpResponseMessage(HttpStatusCode.Unauthorized));
                }
            }
        }

        private void SetDependencies(HttpActionContext actionContext)
        {
            var requestScope = actionContext.Request.GetDependencyScope();

            if (TokenProviderService == null)
            {
                TokenProviderService = requestScope.GetService(typeof(ITokenProviderService)) as ITokenProviderService;
            }
        }

        private AuthenticationErrors Authenticate(HttpActionContext actionContext)
        {
            IEnumerable<string> authHeaderValues;
            actionContext.Request.Headers.TryGetValues("Authorization", out authHeaderValues);

            try
            {
                if (authHeaderValues != null)
                {
                    string bearerToken = authHeaderValues.ElementAt(0);
                    string token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;

                    Thread.CurrentPrincipal = TokenProviderService.ValidateJwtToken(token);
                    if (Thread.CurrentPrincipal != null)
                    {
                        return AuthenticationErrors.AUTHORIZED;
                    }
                }
            }
            catch (SecurityTokenExpiredException)
            {
                return AuthenticationErrors.TOKEN_EXPIRED;
            }
            catch (Exception)
            {
                return AuthenticationErrors.UNAUTHORIZED;
            }

            return AuthenticationErrors.UNAUTHORIZED;
        }

        private bool SkipAuthorization(HttpActionContext actionContext)
        {
            Contract.Assert(actionContext != null);

            return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()
                || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
        }

        private enum AuthenticationErrors
        {
            UNAUTHORIZED,
            TOKEN_EXPIRED,
            AUTHORIZED
        }
    }
}

Как вы можете видеть, он наследуется от класса AuthorizeAttribute.

Вот трассировка стека:

[InvalidOperationException: данный экземпляр фильтра должен реализовывать один или несколько из следующих интерфейсов фильтра: System.Web.Mvc.IAuthorizationFilter, System.Web.Mvc.IActionFilter, System.Web.Mvc.IResultFilter, System.Web.Mvc.IExceptionFilter, System.Web.Mvc.Filters.IAuthenticationFilter.]
System.Web.Mvc.GlobalFilterCollection.ValidateFilterInstance(Объект экземпляр) +403
System.Web.Mvc.GlobalFilterCollection.AddInternal(Фильтр объектов, Nullable`1) +26
System.Web.Mvc.GlobalFilterCollection.Add(фильтр объектов) +31
Examino.API.FilterConfig.RegisterGlobalFilters(GlobalFilterCollection фильтры) в C:\examino\src\Examino.API\App_Start\FilterConfig.cs: 12
Examino.API.WebApiApplication.Application_Start() в C:\examino\SRC\Examino.API\Global.asax.cs: 22

[HttpException (0x80004005): данный экземпляр фильтра должен реализовывать один или несколько из следующих интерфейсов фильтра: System.Web.Mvc.IAuthorizationFilter, System.Web.Mvc.IActionFilter, System.Web.Mvc.IResultFilter, System.Web.Mvc.IExceptionFilter, System.Web.Mvc.Filters.IAuthenticationFilter.]
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext контекст, приложение HttpApplication) +540
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, контекст HttpContext, обработчики MethodInfo []) +186
System.Web.HttpApplication.InitSpecial(состояние HttpApplicationState, Обработчики MethodInfo [], IntPtr appContext, контекст HttpContext) +172
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, контекст HttpContext) +402
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +343

[HttpException (0x80004005): данный экземпляр фильтра должен реализовывать один или несколько из следующих интерфейсов фильтра: System.Web.Mvc.IAuthorizationFilter, System.Web.Mvc.IActionFilter, System.Web.Mvc.IResultFilter, System.Web.Mvc.IExceptionFilter, System.Web.Mvc.Filters.IAuthenticationFilter.]
System.Web.HttpRuntime.FirstRequestInit(контекст HttpContext) +539
System.Web.HttpRuntime.EnsureFirstRequestInit(контекст HttpContext) +125 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, контекст HttpContext) +731

Даже если я реализую, например, интерфейс IAuthenticationFilter, все равно исключается одно и то же исключение.

У кого-то было подобное исключение? Я не смог найти что-то об этом в WebAPI.

Ответ 1

Решено: проблема была местом регистрации фильтра. В MVC вы должны регистрировать фильтры в классе FilterConfing, но в WebAPI вы делаете это в методе Register класса WebApiConfig следующим образом:

config.Filters.Add(new AuthAttribute());

Теперь все работает.