Система аутентификации MVC.NET cookie, использующая веб-Api с аутентификацией токена
У меня есть клиент Mvc 5, у которого есть аутентификация cookie Ownin.
У меня также есть веб-Api, который защищен маркером Owin Bearer (я использовал шаблон VS2013 Web Api, который создает конечную точку Token)
Хорошо, теперь моему клиенту Mvc 5 нужно использовать мой WebApi.
Я создал метод для получения токена-носителя:
internal async Task<string> GetBearerToken(string siteUrl, string Username, string Password)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(siteUrl);
client.DefaultRequestHeaders.Accept.Clear();
HttpContent requestContent = new StringContent("grant_type=password&username=" + Username + "&password=" + Password, Encoding.UTF8, "application/x-www-form-urlencoded");
HttpResponseMessage responseMessage = await client.PostAsync("Token", requestContent);
if (responseMessage.IsSuccessStatusCode)
{
TokenResponseModel response = await responseMessage.Content.ReadAsAsync<TokenResponseModel>();
return response.AccessToken;
}
return "";
}
И в моем действии Mvc я назвал это:
public async Task<ActionResult> Index()
{
var token = await GetBearerToken("http://localhost:6144/", "teste", "123456");
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer "+ token);
var response = await client.GetAsync("http://localhost:6144/api/values");
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsAsync<IEnumerable<string>>();
return Json(data.Result, JsonRequestBehavior.AllowGet);
}
}
}
Все работает отлично... Но мне нужно использовать Web Api во всех моих действиях...
Итак, как я могу сохранить этот токен (несмотря на получение нового токена для каждого запроса) и как проверить, если он истек... Возможно ли сохранить это вместе с cookie аутентификации?
Любые лучшие оценки для решения этого сценария?
Спасибо
Ответы
Ответ 1
Если я правильно понял, ваше клиентское приложение MVC 5 обращается к WebAPI другого приложения.
Клиент MVC 5 использует cookie для аутентификации пользователя. Чтобы получить доступ к WebAPI, вы получаете токен-носитель с конечной точки /Token и отправляете его в заголовок авторизации.
Вы не вызываете WebAPI со своего кода Javascript на стороне клиента, вы просто вызываете его из MVC-действий, запущенных на сервере приложения MVC5.
Получение нового токена перед каждым вызовом службы звучит неправильно. Это означало бы, что каждый раз было бы два раунда. Это не может быть выполнено.
Если бы я получил это право, вы могли бы:
-
Храните токен в объекте Session. До тех пор, пока ваш пользователь приложения MVC будет аутентифицирован и его сеанс будет жив, вы всегда будете иметь тот же токен.
Если он истек, вы получите 401 несанкционированный доступ из WebAPI.
Чтобы сохранить тестовый модуль MVC Testable, вы можете перенести доступ к сеансу в Службу, которую вы вводите в Action (Dependency Injection).
-
вы можете сохранить токен в cookie, подобный уже существующему файлу cookie аутентификации. Таким образом, вам не понадобится сеанс на стороне сервера. Здесь снова я бы обернул доступ, чтобы получить токен из Cookie в службе, которую используют все ваши действия.
Я бы использовал хранилище сеансов. Просто. Прямо вперед.
Но, может быть, я чего-то не хватает
Надеюсь, это поможет вам.
Обратная связь оценена: -)
Ответ 2
Маркер-носитель не является хорошим способом авторизации вашего веб-приложения. Если вы сохраняете токен сервисов в cookie, он будет доступен для клиентов приложений, поэтому уровень сервиса будет уязвим для клиентов приложений. Единственное решение похоже на токен в сеансе, но вы потеряете апатридный характер своего приложения.
Здесь описано, что/как токен-носитель должен использоваться: "Маркер-носитель - это просто большая случайная строка, которую должен представить клиент на каждом вызове API. Носильщики-носители просты, потому что на обоих концах нет специальной сигнатуры или кода проверки. Клиент несет ответственность за хранение маркера в безопасном месте и отправку его с каждым запросом. Сервер отвечает за поиск токена в базе данных и убедиться, что он действительный - это он".
Вот хороший пример использования маркера-носителя в одностраничном приложении, где клиент напрямую разговаривает с сервисом.
В любом случае, я предлагаю вам использовать HMAC authentication, BCrypt или ClientCertificates. Даже amazon использует его для аутентификации запросов REST.
Ответ 3
Если вы хотите управлять маркерами во всех своих действиях, вы должны изменить код для использования настраиваемого фильтра авторизации. Этот фильтр можно добавить ко всем запросам веб-API, всем действиям для контроллера или отдельному действию. Для этого выведите атрибут AuthorizeAttribute и вызовите вызов GetBearerToken из фильтра. Вставьте токен в контекст HTTP для использования во время обработки запроса. Вместо прямого вызова создания экземпляров HttpClient вы можете использовать factory для их создания и добавления соответствующих токенов для аутентификации.
Что касается определения того, истекли ли токены, вы можете добавить дополнительный фильтр, который проверяет, возвращаются ли какие-либо ошибки или альтернативно выдает проверку в авторизационном фильтре. Я не знаю всех ваших требований, поэтому сложно определить подходящее решение там.