Aggiornare:
Ho aggiunto questo link all'altra mia risposta su come utilizzare l'autenticazione JWT per l'API Web ASP.NET qui per chiunque sia interessato a JWT.
Siamo riusciti ad applicare l'autenticazione HMAC per proteggere l'API Web e ha funzionato bene. L'autenticazione HMAC utilizza una chiave segreta per ogni consumatore che sia il consumatore che il server sanno entrambi per che un hash hash un messaggio, HMAC256 dovrebbe essere usato. La maggior parte dei casi, la password con hash del consumatore viene utilizzata come chiave segreta.
Il messaggio viene normalmente generato dai dati nella richiesta HTTP o persino dai dati personalizzati che vengono aggiunti all'intestazione HTTP, il messaggio potrebbe includere:
- Data / ora: ora di invio della richiesta (UTC o GMT)
- Verbo HTTP: GET, POST, PUT, DELETE.
- inserisci dati e stringa di query,
- URL
Sotto il cofano, l'autenticazione HMAC sarebbe:
Il consumatore invia una richiesta HTTP al server web, dopo aver creato la firma (output di hmac hash), il modello di richiesta HTTP:
User-Agent: {agent}
Host: {host}
Timestamp: {timestamp}
Authentication: {username}:{signature}
Esempio per la richiesta GET:
GET /webapi.hmac/api/values
User-Agent: Fiddler
Host: localhost
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
Il messaggio all'hash per ottenere la firma:
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
Esempio di richiesta POST con stringa di query (la firma di seguito non è corretta, solo un esempio)
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
Il messaggio all'hash per ottenere la firma
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
key1=value1&key2=value2&key3=value3
Si noti che i dati del modulo e la stringa di query devono essere in ordine, quindi il codice sul server ottiene la stringa di query e i dati del modulo per creare il messaggio corretto.
Quando la richiesta HTTP arriva al server, viene implementato un filtro di azione di autenticazione per analizzare la richiesta per ottenere informazioni: verbo HTTP, timestamp, uri, dati del modulo e stringa di query, quindi basati su questi per costruire la firma (usa l'hash hmac) con il segreto chiave (password con hash) sul server.
La chiave segreta viene ottenuta dal database con il nome utente sulla richiesta.
Quindi il codice server confronta la firma sulla richiesta con la firma creata; se uguale, l'autenticazione viene passata, altrimenti non è riuscita.
Il codice per creare la firma:
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;
}
Quindi, come prevenire l'attacco replay?
Aggiungi un vincolo per il timestamp, qualcosa del tipo:
servertime - X minutes|seconds <= timestamp <= servertime + X minutes|seconds
(servertime: ora della richiesta in arrivo sul server)
E, memorizza nella cache la firma della richiesta (usa MemoryCache, dovrebbe rimanere nel limite di tempo). Se la richiesta successiva arriva con la stessa firma della richiesta precedente, verrà respinta.
Il codice demo è inserito come qui:
https://github.com/cuongle/Hmac.WebApi