не срабатывает AllowAnonymous в web api 2

372
26 марта 2017, 01:54

Начал изучать web api, дошёл до аутентификации пользователей и тут возник вопрос. Создаю отдельный простой фильтр аутентификации, по примерам, наследуемый от IAuthenticationFilter. В методе AuthenticateAsync прописываю следующее:

public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            context.Principal = null;
            AuthenticationHeaderValue authentication = context.Request.Headers.Authorization;
            if (authentication != null)
            {
                if (authentication.Scheme == "Basic")
                {
                    string[] authData = Encoding.ASCII.GetString(Convert.FromBase64String(authentication.Parameter)).Split(':');
                    if (authData[0] == "testuser" && authData[1] == "Pass1word")
                    {
                        context.Principal = new GenericPrincipal(new GenericIdentity(authData[0]), new[] { "user" });
                    }
                }
            }
            if (context.Principal == null)
            {
                context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[] { new AuthenticationHeaderValue("Basic") }, context.Request);
            }
            return Task.FromResult<object>(null);
        }

Далее в WebApiConfig.cs добавляю фильтр:

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

А в самом контроллере указываю:

[Authorize(Roles ="user")]

И всё бы ничего, даже работает, к контроллеру без аутентификации не пускает. Но, если создать другой контроллер и ему указать

[AllowAnonymous]

то при вызове этого контроллера всё также необходима аутентификация.

Как быть? Помогите разобраться.

Answer 1

Вы добавили фильтр, который применяется для всех контроллеров глобально и не пускает вас без аутентификации. Что хотели - то и получили...

Уберите создание UnauthorizedResult из AuthenticateAsync и реализуйте метод ChallengeAsync как рекомендуют в статье из документации:

public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
    var challenge = new AuthenticationHeaderValue("Basic");
    context.Result = new AddChallengeOnUnauthorizedResult(challenge, context.Result);
    return Task.FromResult(0);
}
public class AddChallengeOnUnauthorizedResult : IHttpActionResult
{
    public AddChallengeOnUnauthorizedResult(AuthenticationHeaderValue challenge, IHttpActionResult innerResult)
    {
        Challenge = challenge;
        InnerResult = innerResult;
    }
    public AuthenticationHeaderValue Challenge { get; private set; }
    public IHttpActionResult InnerResult { get; private set; }
    public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await InnerResult.ExecuteAsync(cancellationToken);
        if (response.StatusCode == HttpStatusCode.Unauthorized)
        {
            // Only add one challenge per authentication scheme.
            if (!response.Headers.WwwAuthenticate.Any((h) => h.Scheme == Challenge.Scheme))
            {
                response.Headers.WwwAuthenticate.Add(Challenge);
            }
        }
        return response;
    }
}

Общая идея - не выдавать 401 всем безусловно - а дождаться пока отработает фильтр авторизации и только требовать логин и пароль только при ошибке доступа.

READ ALSO
Генерация pdf файл Response.AppendHeader

Генерация pdf файл Response.AppendHeader

Генерирую doc файл вот так

255
Как вклиниться в Thread?

Как вклиниться в Thread?

Я как то встречал возможность выполнить код, вклинившись в работающий ThreadНо не могу вспомнить как это делалось

228
Анимация масштабирования

Анимация масштабирования

Подскажите пожалуйста пример кода, чтобы при нажатии кнопки изменялся горизонтальный масштаб, например листбокса listbox1 от 0 до 1, то есть чтобы...

226