WebAPI 2 - IAuthenticationFilter не работает, но AuthorizeAttribute работает - почему? - PullRequest
0 голосов
/ 16 марта 2020

Мне не удается заставить мой настраиваемый фильтр IAuthenticationFilter работать в WebAPI 2. Net стандарт 4.8.

Я создаю приложение с использованием шаблона WebAPI - БЕЗ безопасности. Я добавляю контроллер с приведенным ниже кодом, который также содержит абсолютную базовую c реализацию пользовательского AuthenticationFilter и пользовательского AuthorizeAttribute.

Я могу без проблем попасть в конечную точку «открытого» контроллера.

В другой конечной точке я пытаюсь надеть ТОЛЬКО AuthorizeAttribute, и он работает - запускается код атрибута Authorize "IsAuthorized", а затем действие контроллера. Если я затем заменю этот атрибут настраиваемым фильтром аутентификации - ИЛИ если добавлю к нему фильтр аутентификации, то мой код AuthenticateAsyn c - и установит IPrincipal контекста, но затем, вместо того, чтобы что-то еще работает, следующий вызов идет к ChallengeAsyn c и больше ничего не запускается.

Что я делаю не так?

Я получил код прямо из множества скопированных и вставленных постов в блоге и документов MS, объясняющих AuthenticationFilter .... или так я думал. https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-filters

Обратите внимание, что я проверил этот вопрос: Разница между AuthorizeAttribute и IAuthenticationFilter

... но ответ не относится к IAuthenticationFilter ...

Код для тестового контроллера следующий:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Net;
using System.Web.Http.Filters;
using System.Security.Claims;
using System.Net.Http;
using System.Web.Http.Controllers;

namespace TestApp.Api
{
    // this is not working currently due to the fact that we have to do the wonky security for aspx pages
    public class TestFilterAttribute : Attribute, IAuthenticationFilter
    {
        public class BasicActionResult : IHttpActionResult
        {
            private HttpResponseMessage message;
            public BasicActionResult(HttpResponseMessage message)
            {
                this.message = message;
            }
            public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) => Task.FromResult(message);
        }

        public bool AllowMultiple => false;

        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            context.Result = new BasicActionResult(context.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid Authorization"));
            return Task.FromResult(0);
        }

        public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.Name, "testUser"));
            claims.Add(new Claim("email", "testUser@test.local"));
            var id = new ClaimsIdentity(claims, "Token");
            context.Principal = new ClaimsPrincipal(new ClaimsIdentity[] { id });
            return Task.FromResult(0);
        }
    }

    public class TestAuthorizeAttribute : AuthorizeAttribute
    {
        protected override bool IsAuthorized(HttpActionContext context)
        {
            var principal = context.Request.GetRequestContext().Principal as ClaimsPrincipal;
            if (principal == null) return false;
            return true;
        }


    }

    [RoutePrefix("api/test")]
    public class TestController : ApiController
    {
        [HttpGet]
        [Route("open")]
        public string TestOpen()
        {
            return "TestOpen Works";
        }

        [HttpGet]
        [Route("secure")]
        [TestAuthorize]
        public string TestSecured()
        {
            return "TestSecured Works";
        }
    }
}
...