Aktualizacja:
Dodałem ten link do mojej innej odpowiedzi, jak używać uwierzytelniania JWT dla API sieci Web ASP.NET tutaj dla wszystkich zainteresowanych JWT.
Udało nam się zastosować uwierzytelnianie HMAC do bezpiecznego interfejsu API sieci Web i działało dobrze. Uwierzytelnianie HMAC używa tajnego klucza dla każdego konsumenta, który zarówno klient, jak i serwer wiedzą, że hmac hash wiadomość, należy użyć HMAC256. W większości przypadków zaszyfrowane hasło konsumenta jest używane jako tajny klucz.
Wiadomość zwykle jest zbudowana z danych w żądaniu HTTP lub nawet niestandardowych danych, które są dodawane do nagłówka HTTP, wiadomość może zawierać:
- Znacznik czasu: godzina wysłania żądania (UTC lub GMT)
- Czasownik HTTP: GET, POST, PUT, DELETE.
- przesłać dane i ciąg zapytania,
- URL
Pod maską uwierzytelnianie HMAC byłoby:
Konsument wysyła żądanie HTTP do serwera WWW, po zbudowaniu podpisu (dane wyjściowe skrótu hmac) szablon żądania HTTP:
User-Agent: {agent}
Host: {host}
Timestamp: {timestamp}
Authentication: {username}:{signature}
Przykład żądania GET:
GET /webapi.hmac/api/values
User-Agent: Fiddler
Host: localhost
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
Wiadomość do skrótu, aby uzyskać podpis:
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
Przykład żądania POST z ciągiem zapytania (poniższy podpis jest niepoprawny, tylko przykład)
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
Wiadomość do skrótu, aby uzyskać podpis
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
key1=value1&key2=value2&key3=value3
Należy pamiętać, że dane formularza i ciąg zapytania powinny być w porządku, więc kod na serwerze otrzymuje ciąg zapytania i dane formularza, aby zbudować poprawny komunikat.
Gdy żądanie HTTP przychodzi do serwera, wdrażany jest filtr akcji uwierzytelniania, który analizuje żądanie w celu uzyskania informacji: czasownik HTTP, znacznik czasu, identyfikator użytkownika, dane formularza i ciąg zapytania, a następnie na podstawie tych danych do zbudowania podpisu (użyj skrótu hmac) za pomocą klucza tajnego klucz (hashowane hasło) na serwerze.
Tajny klucz jest pobierany z bazy danych z nazwą użytkownika na żądanie.
Następnie kod serwera porównuje podpis na żądanie z podpisem zbudowanym; jeśli jest równy, uwierzytelnienie jest przekazywane, w przeciwnym razie nie powiedzie się.
Kod do budowy podpisu:
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;
}
Jak więc zapobiec atakowi powtórek?
Dodaj ograniczenie znacznika czasu, na przykład:
servertime - X minutes|seconds <= timestamp <= servertime + X minutes|seconds
(servertime: czas nadejścia żądania do serwera)
I buforuj podpis żądania w pamięci (użyj MemoryCache, należy zachować limit czasu). Jeśli następne żądanie zostanie opatrzone tym samym podpisem co poprzednie, zostanie odrzucone.
Kod demonstracyjny jest umieszczony tutaj:
https://github.com/cuongle/Hmac.WebApi
Proponuję zacząć od najprostszych rozwiązań - może wystarczy proste uwierzytelnianie podstawowe HTTP + HTTPS w twoim scenariuszu.
Jeśli nie (na przykład nie możesz używać protokołu https lub potrzebujesz bardziej złożonego zarządzania kluczami), możesz spojrzeć na rozwiązania oparte na HMAC, jak sugerują inni. Dobrym przykładem takiego interfejsu API jest Amazon S3 ( http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html )
Napisałem post na blogu o uwierzytelnianiu opartym na HMAC w ASP.NET Web API. Omówiono zarówno usługę Web API, jak i klienta Web API, a kod jest dostępny na bitbucket. http://www.piotrwalat.net/hmac-authentication-in-asp-net-web-api/
Oto post dotyczący podstawowego uwierzytelniania w interfejsie API sieci Web: http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/
Pamiętaj, że jeśli zamierzasz udostępniać interfejs API stronom trzecim, najprawdopodobniej będziesz również odpowiedzialny za dostarczanie bibliotek klienckich. Uwierzytelnianie podstawowe ma tutaj znaczącą zaletę, ponieważ jest obsługiwane na większości platform programistycznych od razu po wyjęciu z pudełka. Z drugiej strony HMAC nie jest tak ustandaryzowany i będzie wymagał niestandardowej implementacji. Powinny być stosunkowo proste, ale nadal wymagają pracy.
PS. Istnieje również opcja użycia certyfikatów HTTPS +. http://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/
źródło
Czy próbowałeś DevDefined.OAuth?
Użyłem go, aby zabezpieczyć moją WebApi za pomocą 2-Legged OAuth. Z powodzeniem przetestowałem to również z klientami PHP.
Korzystanie z tej biblioteki jest bardzo łatwe, aby dodać obsługę protokołu OAuth. Oto, w jaki sposób można wdrożyć dostawcę interfejsu API sieci Web ASP.NET MVC:
1) Pobierz kod źródłowy DevDefined.OAuth: https://github.com/bittercoder/DevDefined.OAuth - najnowsza wersja pozwala na
OAuthContextBuilder
rozszerzalność.2) Zbuduj bibliotekę i odwołaj się do niej w swoim projekcie Web API.
3) Utwórz niestandardowy konstruktor kontekstów, aby wspierać budowanie kontekstu z
HttpRequestMessage
:4) Skorzystaj z tego samouczka, aby utworzyć dostawcę OAuth: http://code.google.com/p/devdefined-tools/wiki/OAuthProvider . W ostatnim kroku (Przykład dostępu do chronionych zasobów) możesz użyć tego kodu w swoim
AuthorizationFilterAttribute
atrybucie:Wdrożyłem własnego dostawcę, więc nie przetestowałem powyższego kodu (oprócz oczywiście tego,
WebApiOAuthContextBuilder
którego używam u mojego dostawcy), ale powinien on działać dobrze.źródło
Interfejs API sieci Web wprowadził atrybut
[Authorize]
zapewniający bezpieczeństwo. Można to ustawić globalnie (global.asx)Lub na kontrolera:
Oczywiście twój typ uwierzytelnienia może się różnić i możesz chcieć przeprowadzić własne uwierzytelnianie, gdy to nastąpi, możesz znaleźć przydatne dziedziczenie po autoryzacji atrybutu i rozszerzenie go, aby spełnić twoje wymagania:
A w twoim kontrolerze:
Oto link do innej niestandardowej implementacji autoryzacji WebApi:
http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/
źródło
AuthorizeAttribute
, ponieważ istnieją dwie różne klasy o tej samej nazwie, w różnych przestrzeniach nazw: 1. System.Web.Mvc.AuthorizeAttribute -> dla kontrolerów MVC 2. System.Web.Http.AuthorizeAttribute -> dla WebApi.Jeśli chcesz zabezpieczyć swój interfejs API w sposób zgodny z serwerem (bez przekierowania na stronę internetową w celu uwierzytelnienia 2-etapowego). Możesz spojrzeć na protokół OAuth2 Client Credentials Grant.
https://dev.twitter.com/docs/auth/application-only-auth
Opracowałem bibliotekę, która może pomóc w łatwym dodaniu tego rodzaju wsparcia do interfejsu WebAPI. Możesz zainstalować go jako pakiet NuGet:
https://nuget.org/packages/OAuth2ClientCredentialsGrant/1.0.0.0
Biblioteka jest przeznaczona dla .NET Framework 4.5.
Po dodaniu pakietu do projektu utworzy on plik readme w katalogu głównym projektu. Możesz spojrzeć na ten plik readme, aby zobaczyć, jak skonfigurować / używać tego pakietu.
Twoje zdrowie!
źródło
kontynuując odpowiedź @ Cuong Le, moje podejście do zapobiegania atakowi powtórek byłoby
// Szyfruj czas uniksowy po stronie klienta przy użyciu wspólnego klucza prywatnego (lub hasła użytkownika)
// Wyślij jako część nagłówka żądania na serwer (WEB API)
// Odszyfruj czas uniksowy na serwerze (WEB API) przy użyciu wspólnego klucza prywatnego (lub hasła użytkownika)
// Sprawdź różnicę czasu między czasem uniksowym klienta a czasem uniksowym serwera, nie powinna być większa niż x sek
// jeśli identyfikator użytkownika / hasło skrótu są poprawne, a odszyfrowany UnixTime znajduje się w odległości x sekund od czasu serwera, to jest to prawidłowe żądanie
źródło