更新:
ASP.NET Web APIでJWT認証を使用する方法を、JWTに関心のあるユーザー向けにここに追加しました。
安全なWeb APIにHMAC認証を適用することに成功しましたが、問題なく動作しました。HMAC認証は、コンシューマーとサーバーの両方がメッセージをhmacハッシュすることを知っている各コンシューマーの秘密鍵を使用します。HMAC256を使用する必要があります。ほとんどの場合、コンシューマのハッシュ化されたパスワードが秘密鍵として使用されます。
メッセージは通常、HTTPリクエストのデータ、またはHTTPヘッダーに追加されるカスタマイズされたデータから構築され、メッセージには次のものが含まれます。
- タイムスタンプ:リクエストが送信された時刻(UTCまたはGMT)
- HTTP動詞:GET、POST、PUT、DELETE。
- 投稿データとクエリ文字列、
- URL
内部的には、HMAC認証は次のようになります。
コンシューマーは、HTTPリクエストのテンプレートである署名(hmacハッシュの出力)を構築した後、HTTPリクエストをWebサーバーに送信します。
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、フォームデータ、クエリ文字列)を取得し、これらに基づいて、シークレットを使用して署名(hmacハッシュを使用)を構築しますサーバー上のキー(ハッシュされたパスワード)。
秘密鍵は、要求に応じてユーザー名とともにデータベースから取得されます。
次に、サーバーコードはリクエストの署名と作成された署名を比較します。等しい場合、認証は成功し、そうでない場合は失敗します。
署名を作成するコード:
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
(servertime:サーバーに到着するリクエストの時間)
また、リクエストの署名をメモリにキャッシュします(MemoryCacheを使用します。時間の制限内に留めてください)。次のリクエストに前のリクエストと同じ署名が付いている場合、そのリクエストは拒否されます。
デモコードは次のように配置されます:https :
//github.com/cuongle/Hmac.WebApi