Оновлення:
Я додав це посилання до своєї іншої відповіді, як використовувати автентифікацію JWT для веб-API ASP.NET тут для всіх, хто цікавиться JWT.
Нам вдалося застосувати автентифікацію HMAC для захисту веб-API, і він працював нормально. Для аутентифікації HMAC використовується секретний ключ для кожного споживача, який і споживач, і сервер знають, щоб hmac хеш повідомлення, HMAC256 слід використовувати. У більшості випадків хеш-пароль споживача використовується як секретний ключ.
Повідомлення зазвичай будується з даних запиту HTTP або навіть налаштованих даних, які додаються до заголовка HTTP, повідомлення може включати:
- Часова позначка: час надсилання запиту (UTC або GMT)
- HTTP дієслово: GET, POST, PUT, DELETE.
- розмістити дані та рядок запиту,
- URL-адреса
Під капотом аутентифікація HMAC буде такою:
Споживач надсилає HTTP-запит на веб-сервер після складання підпису (вихід хмакового хеша) шаблону HTTP запиту:
User-Agent: {agent}
Host: {host}
Timestamp: {timestamp}
Authentication: {username}:{signature}
Приклад для отримання GET запиту:
GET /webapi.hmac/api/values
User-Agent: Fiddler
Host: localhost
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
Повідомлення хешу для отримання підпису:
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
Приклад для POST-запиту із рядком запиту (підпис нижче не правильний, лише приклад)
POST /webapi.hmac/api/values?key2=value2
User-Agent: Fiddler
Host: localhost
Content-Type: application/x-www-form-urlencoded
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
key1=value1&key3=value3
Повідомлення хешу, щоб отримати підпис
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
key1=value1&key2=value2&key3=value3
Зверніть увагу, що дані форми та рядок запиту повинні бути в порядку, тому код на сервері отримує рядок запиту та формує дані для створення правильного повідомлення.
Коли HTTP-запит надходить на сервер, реалізується фільтр дій автентифікації для розбору запиту для отримання інформації: дієслова HTTP, часової позначки, uri, даних форми та рядка запиту, а потім на їх основі будувати підпис (використовувати хмак хеш) із секретом ключ (хешований пароль) на сервері.
Секретний ключ отримується з бази даних з ім'ям користувача за запитом.
Потім код сервера порівнює підпис під запитом із вбудованим підписом; якщо рівне, автентифікація передається, інакше вона не вдалася.
Код для складання підпису:
private static string ComputeHash(string hashedPassword, string message)
{
var key = Encoding.UTF8.GetBytes(hashedPassword.ToUpper());
string hashString;
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
Отже, як запобігти повторній атаці?
Додайте обмеження для позначки часу, наприклад:
servertime - X minutes|seconds <= timestamp <= servertime + X minutes|seconds
(час сервера: час надходження запиту на сервер)
І, кешуйте підпис запиту в пам'яті (використовуйте MemoryCache, слід зберігати в обмеженому періоді часу). Якщо наступний запит має такий самий підпис із попереднім запитом, він буде відхилений.
Демо-код ставиться так:
https://github.com/cuongle/Hmac.WebApi