Маркер доступа (
access token) вдается один раз. На стороне клиента сохраняется в
sessiongStorage либо в
cookies. Используется при каждом запросе к
API. Как правило, передавать маркер доступа лучше через заголовки. При использовании
HTTPS заголовки будут зашифрованы.
Для повышения безопасности, сервер может выдавать маркер доступа привязанный к конкретному
IP (можно еще усложнить, например проверять браузер, тип системы и т.п.). Если адрес клиента не совпадает с адресом в базе, то аннулировать маркер доступа и предлагать клиенту получить новый маркер доступа.
Срок действия маркер доступа
может должен быть ограничен. Срок действия зависит от условий использования и необходимой степени безопасности. Например, если маркер привязан к
IP, то срок действия вполне может быть продолжительным.
На стороне сервера, для проверки доступа можно сделать отдельный фильтр, примерно как показано в коде ниже:
class ApiAccess : AuthorizeAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException("actionContext");
}
if (!this.IsAuthorized(actionContext))
{
return;
}
}
protected override bool IsAuthorized(HttpActionContext actionContext)
{
bool isAuthroized = base.IsAuthorized(actionContext);
// логика проверки доступа
IEnumerable<string> authItems;
if (actionContext.Request.Headers.TryGetValues("Authorization", out authItems))
{
var auth = authItems.First().Split(' ');
var token = service.GetToken(auth.Last());
// ...
}
return isAuthroized;
}
}
Фильтр добавляется к контроллерам
WebAPI, где необходима проверка доступа:
[ApiAccess]
public class FileServerController : ApiController
{
// ...
}
Со стороны клиента, проще сделать вспомогательный метод, который будет отправлять запросы в API с использованием маркера доступа, а также проверять необходимость получения нового маркера доступа (если сервер вернет ошибку). Примерно, как показано в следующем коде:
let url = '/методAPI';
let data = {}; // параметры запроса
let headers = {
'Authorization': 'ANYNAMEHERE ' + sessionStorage.getItem('token')
};
$.ajax({
cache: false,
processData: false,
type: 'POST',
url: url,
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(data),
headers: headers,
success: (result) => {
// успех
},
error: (x, textStatus, errorThrown) => {
// ошибка
// на сервер можно сделать исключение для плохих маркеров доступа
// и проверить, если responseText содержит данный тип исключения,
// то требовать у пользователя повторную авторизацию
if (x.responseText) {
let exception = JSON.parse(x.responseText);
// AccessDeniedException - тип исключения в WebAPI,
// (скорее всего полное имя типа придется указывать)
if (exception.ExceptionType == 'AccessDeniedException') {
// ...
}
}
}
});
Что касается получения пользователем маркера доступа, то это можно сделать любым удобным способом. Например, показывать модальное окно для ввода логина и пароля, или перенаправлять на отдельную страницу.
Если
API используется через отдельный (независимый от
API) сайт, который авторизует пользователей, то пользователя можно не привлекать к процедуре получения нового маркера доступа, сайт это может сделать сам и передать новый маркер своему пользователю.
Если
API используется в браузере, как есть, то маркер доступа можно передавать в параметрах запроса. Однако это небезопасно, т.к. данные будут в открытом виде.