Проблема ASP.NET WebApi FormsAuthentication 401 (неавторизованная)

Я изучал, как работает авторизация в ASP.Net WebApi, и наткнулся на ответ Дарина Димитрова в другом сообщении ( Аутентификация веб-API ASP.NET ), и мне нужна помощь, чтобы понять, почему я получаю ошибку 401.

Следуя коду Дарина, я создал проект WebApi и добавил следующие контроллеры и модель:

AccountController.cs

using System.Web.Http;
using System.Web.Security;
using AuthTest.Models;

namespace AuthTest.Controllers
{
    public class AccountController : ApiController
    {
        public bool Post(LogOnModel model)
        {
            if (model.Username == "john" && model.Password == "secret")
            {
                FormsAuthentication.SetAuthCookie(model.Username, false);
                return true;
            }

            return false;
        }
    }
}

UsersController.cs

using System.Web.Http;

namespace AuthTest.Controllers
{
    [Authorize]
    public class UsersController : ApiController
    {
        public string Get()
        {
            return "This is top secret material that only authorized users can see";
        }
    }
}

Логонмодел.cs

namespace AuthTest.Models
{
    public class LogOnModel
    {
        public string Username { get; set; }
        public string Password { get; set; }
    }
}

Я создал приложение Web Forms с двумя кнопками и меткой для целей тестирования.

Default.aspx.cs

using System;
using System.Net.Http;
using System.Threading;

namespace AuthTestWebForms
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected void ButtonAuthorizeClick(object sender, EventArgs e)
        {
            using (var httpClient = new HttpClient())
            {
                var response = httpClient.PostAsJsonAsync(
                    "http://localhost/authtest/api/account",
                    new { username = "john", password = "secret" },
                    CancellationToken.None
                ).Result;
                response.EnsureSuccessStatusCode();

                bool success = response.Content.ReadAsAsync<bool>().Result;
                if (success)
                {
                    //LabelResponse.Text = @"Credentials provided";
                    var secret = httpClient.GetStringAsync("http://localhost/authtest/api/users");
                    LabelResponse.Text = secret.Result;
                }
                else
                {
                    LabelResponse.Text = @"Sorry, you provided the wrong credentials";
                }
            }
        }

        protected void ButtonTestAuthClick(object sender, EventArgs e)
        {
            using (var httpClient = new HttpClient())
            {
                var secret = httpClient.GetStringAsync("http://localhost/authtest/api/users");
                LabelResponse.Text = secret.Result;
            }
        }
    }
}

Когда я нажимаю кнопку и запускаю ButtonAuthorizeClick(), он запускает контроллер для учетной записи, а затем запускает контроллер для пользователей, и все в порядке.

Если я затем нажму ButtonTestAuthClick(), я получу ошибку 401 (Unauthorized).

Когда я ищу файл cookie ASPXAUTH в Chrome или FireFox, я его не вижу, поэтому я не уверен на 100%, почему работает ButtonAuthorizeClick() и что мне нужно сделать, чтобы заставить ButtonTestAuthClick() работать.

Спасибо за любую помощь, кто-нибудь может бросить мне путь.


person Richard O'Neil    schedule 12.10.2012    source источник


Ответы (3)


У меня была аналогичная проблема, но не через клиентскую страницу веб-форм, а с вызовами JavaScript и AJAX. Оказывается, я оставил режим аутентификации в web.config, оставив «Нет». Очевидно, что здесь необходимо включить проверку подлинности с помощью форм, чтобы метод FormsAuthentication.SetAuthCookie() имел какой-либо эффект.

<authentication mode="Forms" />

Как только я исправил эту оплошность, все стало работать нормально. :-)

person DrBoom    schedule 02.11.2012
comment
Черт... и в моем тестовом приложении, и в API установлены формы, и я все еще получаю тот же ответ. Спасибо за ответ, однако. - person Richard O'Neil; 12.11.2012

Вы вызываете веб-API с аутентификацией посередине. Почему бы вам не аутентифицировать пользователя на стороне клиента с помощью ajax?

Проблема здесь в том, что каждый раз, когда вы отправляете запрос к веб-API с помощью HttpClient, на самом деле это новый веб-запрос, обрабатываемый сервером. Вся информация о файлах cookie не будет храниться в текущем запросе. Чтобы поддерживать этот сценарий, вам необходимо самостоятельно обрабатывать файл cookie.

Например: установите cookie ASPXAUTH в заголовки asp.net в методе ButtonAuthorizeClick, если он есть в ответе. Установите для файла cookie ASPXAUTH значение HttpRequestMessage и отправьте его с помощью HttpClient.

Веб-API недавно добавил поддержку использования HttpServer для создания внутрипроцессного сервера и может напрямую отправлять запрос текущему обработчику сообщений в текущем процессе. Таким образом, вы можете написать код, например:

HttpClient c = new HttpClient(new HttpServer(GlobalConfiguration.DefaultHandler));
c.GetStringAsync("http://localhost/api/Values").Wait();

Чтобы отправить ваш запрос внутри процесса, чтобы заголовок файла cookie, установленный в действии веб-API, все еще находился в конвейере текущего запроса. Регистрация кажется не в выпуске RTM. Вы можете попробовать ночную сборку http://aspnetwebstack.codeplex.com/discussions/353867.

person Hongye Sun    schedule 12.10.2012

Хотя уже поздно, клиент в ButtonTestAuthClick не является браузером. Здесь это объект httpClient. Таким образом, вам нужно программно установить файл cookie, сгенерированный с другой кнопки.

person Houssam Hamdan    schedule 22.02.2017