Аутентификация пользователя в ASP.NET Web API

150

Эта тема была невероятно запутанной для меня. Я новичок в приложениях HTTP, но мне нужно разработать клиент для iPhone, который будет использовать данные JSON откуда-то. Я выбрал Web API от MS, потому что это казалось достаточно простым, но когда дело доходит до аутентификации пользователей, все становится довольно сложно.

Я поражен тем, как мне не удалось найти наглядный пример того, как аутентифицировать пользователя, прямо с экрана входа в систему и использования Authorizeатрибута в моих ApiControllerметодах после нескольких часов поиска в Google.

Это не вопрос, а просьба привести пример того, как именно это сделать. Я посмотрел на следующих страницах:

Несмотря на то, что они объясняют, как обрабатывать неавторизованные запросы, они явно не демонстрируют что-то вроде LoginControllerили что-то подобное, чтобы запрашивать учетные данные пользователя и проверять их.

Кто-нибудь готов написать хороший простой пример или указать мне правильное направление, пожалуйста?

Спасибо.

Луис Агилар
источник
1
На этот же вопрос я ответил на один и тот же вопрос: stackoverflow.com/questions/11775594/…
cuongle
Для Web Api с asp.net вы можете просто использовать модуль cookie и formautauthentication, как если бы вы использовали приложение mvc (если хотите). Таким образом, в своем веб-API-коде вы можете затем проверить принципала, чтобы увидеть, например, вошел ли пользователь в систему (например, как и раньше).
Эллиот
Также посмотрите на мой ответ для stackoverflow.com/questions/11775594/…
Varun Chatterji
Я настоятельно рекомендую многим людям прочитать статью asp.net/web-api/overview/security/… .
Youngjae

Ответы:

176

Я поражен тем, что мне не удалось найти четкий пример того, как аутентифицировать пользователя прямо с экрана входа в систему до использования атрибута Authorize для моих методов ApiController после нескольких часов поиска в Google.

Это потому, что вы запутались в этих двух понятиях:

  • Аутентификация - это механизм, с помощью которого системы могут безопасно идентифицировать своих пользователей. Системы аутентификации дают ответы на вопросы:

    • Кто пользователь?
    • Действительно ли пользователь является тем, кем он / она представляет себя?
  • Авторизация - это механизм, с помощью которого система определяет, какой уровень доступа должен иметь конкретный аутентифицированный пользователь к защищенным ресурсам, контролируемым системой. Например, система управления базой данных может быть спроектирована так, чтобы предоставлять определенным указанным лицам возможность извлекать информацию из базы данных, но не возможность изменять данные, хранящиеся в базе данных, в то же время предоставляя другим лицам возможность изменять данные. Системы авторизации дают ответы на вопросы:

    • Имеет ли пользователь X право доступа к ресурсу R?
    • Имеет ли пользователь X право выполнять операцию P?
    • Имеет ли пользователь X право выполнять операцию P на ресурсе R?

AuthorizeАтрибут в MVC используется для применения правил доступа, например:

 [System.Web.Http.Authorize(Roles = "Admin, Super User")]
 public ActionResult AdministratorsOnly()
 {
     return View();
 }

Приведенное выше правило разрешит доступ к методу только пользователям с правами администратора и суперпользователя.

Эти правила также можно установить в файле web.config, используя locationэлемент. Пример:

  <location path="Home/AdministratorsOnly">
    <system.web>
      <authorization>
        <allow roles="Administrators"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>

Однако перед выполнением этих правил авторизации вы должны пройти аутентификацию на текущем веб-сайте .

Несмотря на то, что они объясняют, как обрабатывать неавторизованные запросы, они явно не демонстрируют что-то вроде LoginController или чего-то подобного, чтобы запрашивать учетные данные пользователя и проверять их.

Отсюда мы можем разделить проблему на две части:

  • Аутентификация пользователей при использовании служб веб-API в одном веб-приложении

    Это будет самый простой подход, потому что вы будете полагаться на аутентификацию в ASP.Net

    Это простой пример:

    Web.config

    <authentication mode="Forms">
      <forms
        protection="All"
        slidingExpiration="true"
        loginUrl="account/login"
        cookieless="UseCookies"
        enableCrossAppRedirects="false"
        name="cookieName"
      />
    </authentication>

    Пользователи будут перенаправлены на маршрут учетной записи / входа в систему , где вы будете создавать пользовательские элементы управления для запроса учетных данных пользователя, а затем вы будете устанавливать cookie-файл аутентификации, используя:

        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    
  • Межплатформенная аутентификация

    Этот случай может быть, когда вы предоставляете только сервисы веб-API в веб-приложении, поэтому у вас будет другой клиент, использующий сервисы, клиент может быть другим веб-приложением или любым приложением .Net (Win Forms, WPF, консоль, служба Windows, и т.д)

    Например, предположим, что вы будете использовать службу веб-API из другого веб-приложения в том же сетевом домене (в интрасети), в этом случае вы можете полагаться на проверку подлинности Windows, предоставляемую ASP.Net.

    <authentication mode="Windows" />

    Если ваши сервисы доступны в Интернете, вам необходимо будет передать аутентифицированные токены каждой службе Web API.

    Для получения дополнительной информации, обратите внимание на следующие статьи:

Jupaol
источник
3
Вот Это Да! Это то, что я называю ответом. Итак, в заключение. Я планирую сделать следующее: 1. Создать контроллер учетной записи с методом Login, который получает имя пользователя и пароль через HTTPS и возвращает результат входа в систему и токен. 2. Клиент сохраняет токен и отправляет его в виде заголовка (больше не HTTPS) в запросе, который проверяется веб-сервером. Это хороший подход? Тогда мое последнее сомнение заключается в том, как контролировать подделку токена и истечение срока действия. Это возможно?
Луис Агилар
6
@Jupaol Я думаю, что говорю от многих разработчиков веб-API, я не могу использовать проверку подлинности с помощью форм, потому что у меня нет веб-сайта, а клиенты не используют браузер, а также я не могу использовать встроенную проверку подлинности, поскольку пользователи могут находиться в любой точке мира на любом устройстве ( отсюда и веб-API), так что мне использовать?
markmnl
21
Я не понимаю, почему этот ответ получил так много голосов. Речь идет не о ASP.NET Web API, а о ASP.NET MVC.
Бастьен Вандамм
3
Я хотел бы повторить комментарий B413 и указать, что этот вопрос специально задает Web API
Julien
6
Это самый «неправильный» ответ на SO? Ответ на самом деле не говорит о веб-API, который сильно отличается от веб-приложения MVC! Как @ B413, я в полном шоке!
stt106
15

Если вы хотите пройти аутентификацию по имени пользователя и паролю и без файла cookie авторизации, атрибут MVC4 Authorize не будет работать сразу после установки. Тем не менее, вы можете добавить следующий вспомогательный метод к вашему контроллеру для принятия базовых заголовков аутентификации. Вызывайте его с самого начала методов вашего контроллера.

void EnsureAuthenticated(string role)
{
    string[] parts = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(Request.Headers.Authorization.Parameter)).Split(':');
    if (parts.Length != 2 || !Membership.ValidateUser(parts[0], parts[1]))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "No account with that username and password"));
    if (role != null && !Roles.IsUserInRole(parts[0], role))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "An administrator account is required"));
}

Со стороны клиента этот помощник создает HttpClientзаголовок с аутентификацией:

static HttpClient CreateBasicAuthenticationHttpClient(string userName, string password)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(userName + ':' + password)));
    return client;
}
Эдвард Брей
источник
Просто хотел прокомментировать, что я искал простой способ использования отраслевого стандарта для передачи учетных данных в заголовке. Этот пример показал основы как со стороны сервера, так и со стороны клиента, и это было все, что мне было нужно.
da_jokker
9

Я работаю над проектом MVC5 / Web API, и мне нужно было получить разрешение для методов Web Api. Когда мое индексное представление загружается впервые, я вызываю метод веб-API 'token', который, я считаю, создается автоматически.

Код на стороне клиента (CoffeeScript) для получения токена:

getAuthenticationToken = (username, password) ->
    dataToSend = "username=" + username + "&password=" + password
    dataToSend += "&grant_type=password"
    $.post("/token", dataToSend).success saveAccessToken

В случае успеха вызывается следующее, которое сохраняет токен аутентификации локально:

saveAccessToken = (response) ->
    window.authenticationToken = response.access_token

Затем, если мне нужно сделать Ajax-вызов для метода веб-API с тегом [Authorize], я просто добавляю следующий заголовок к своему Ajax-вызову:

{ "Authorization": "Bearer " + window.authenticationToken }
ProfNimrod
источник
Откуда response.access_tokenвзялся. Вы устанавливаете это из кода C # ..?
shashwat
Объект «response» возвращается методом «token».
ПрофНимрод
Я не смотрел на роли. Этот подход просто дает вам токен доступа, чтобы вы могли вызывать методы WebApi, украшенные тегом [Authorize]. Предположительно, когда вы вызываете любой из этих методов, вы можете проверить роли. stackoverflow.com/questions/19689570/mvc-5-check-user-role может помочь.
ПрофНимрод
И где в этом решении вы на самом деле аутентифицируете своего пользователя?
Крейг Бретт
Конечная точка / token создается автоматически для любого нового проекта Web API. Код, стоящий за этим, где пользователь аутентифицирован. Это немного сложнее, если вы добавили контроллер Web API в существующий проект MVC.
ПрофНимрод