최신 정보:
JWT에 관심이있는 모든 사람들을 위해 ASP.NET 웹 API에 JWT 인증을 사용하는 방법에 대한 다른 답변 에이 링크를 추가했습니다 .
웹 API를 보호하기 위해 HMAC 인증을 적용했으며 정상적으로 작동했습니다. HMAC 인증은 소비자와 서버 모두 메시지를 hmac 해시하는 것으로 알고있는 각 소비자에 대해 비밀 키를 사용하므로 HMAC256을 사용해야합니다. 대부분의 경우 소비자의 해시 비밀번호는 비밀 키로 사용됩니다.
메시지는 일반적으로 HTTP 요청의 데이터 또는 HTTP 헤더에 추가 된 사용자 정의 데이터로 작성되며 메시지에는 다음이 포함될 수 있습니다.
- 타임 스탬프 : 요청이 전송 된 시간 (UTC 또는 GMT)
- HTTP 동사 : GET, POST, PUT, DELETE
- 데이터 게시 및 쿼리 문자열
- URL
기본적으로 HMAC 인증은 다음과 같습니다.
소비자는 HTTP 요청의 템플릿 인 서명 (hmac 해시 출력)을 작성한 후 웹 서버에 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, 양식 데이터 및 쿼리 문자열과 같은 정보를 얻기 위해 요청을 구문 분석 한 다음이를 기반으로 시크릿으로 서명 (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
(서버 시간 : 요청이 서버에 들어오는 시간)
그리고 요청의 서명을 메모리에 캐시하십시오 (MemoryCache 사용, 시간 제한을 유지해야 함). 다음 요청에 이전 요청과 동일한 서명이있는 경우 거부됩니다.
데모 코드는 다음과 같습니다.
https://github.com/cuongle/Hmac.WebApi