아래 표는 대표적인 해시 함수중 하나인 SHA1
에 특정 입력 값을 넣었을 때 어떤 결과가 리턴되는지 보여주는 예시이다.
비밀번호 | 해시 함수(SHA1) 리턴 값 |
---|---|
‘password’ | ‘5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8’ |
‘Password’ | ‘8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D’ |
‘kimcoding’ | ‘61D17C8312E8BC24D126BE182BC674704F954C5A’ |
SHA1
함수를 직접 사용해 볼 수도 있다.솔트는 소금이라는 뜻으로, 말 그대로 소금을 치듯 해싱 이전 값에 임의의 값을 더해 데이터가 유출되더라도 해싱 이전의 값을 알아내기 더욱 어렵게 만드는 방법이다.
비밀번호 + 솔트 | 해시 함수(SHA1) 리턴 값 |
---|---|
‘password’ + ‘salt’ | ‘C88E9C67041A74E0357BEFDFF93F87DDE0904214’ |
‘Password’ + ‘salt’ | ‘38A8FDE622C0CF723934BA7138A72BEACCFC69D4’ |
‘kimcoding’ + ‘salt’ | ‘8607976121653D418DDA5F6379EB0324CA8618E6’ |
사이트 관리자는 사용자의 비밀번호를 알고 있을 필요가 없다.
오히려 사용자들의 비밀번호를 알고 있다면, 이를 얼마든지 악용할 수 있기 때문에 심각한 문제가 생길 수도 있다.
그래서 보통 비밀번호를 데이터베이스에 저장할 때, 복호화가 불가능하도록 해싱하여 저장하게 된다. 해싱은 복호화가 불가능하므로 사이트 관리자도 정확한 비밀번호를 알 수 없게 된다.
그럼 서버 측에서 비밀번호를 모르는 상태에서 어떻게 로그인 요청을 처리할 수 있는 걸까?
방법은 간단하다. 해싱한 값끼리 비교해서 일치하는지 확인하는 것이다.
꼭 정확한 값을 몰라도, 해싱한 값이 일치한다면 정확한 비밀번호를 입력했다는 뜻이 되기 때문에, 해싱 값으로만 로그인 요청을 처리하는 데에도 전혀 문제가 없다.
- 사용자가 인증 정보를 담아 서버에 로그인 요청을 보낸다.
- 서버는 데이터베이스에 저장된 사용자의 인증 정보를 확인한다.
- 인증에 성공했다면 해당 사용자의 인증 및 권한 정보를 서버의 비밀 키와 함께 토큰으로 암호화한다.
- 생성된 토큰을 클라이언트로 전달한다.
- HTTP 상에서 인증 토큰을 보내기 위해 사용하는 헤더인 Authorization 헤더를 사용하거나, 쿠키로 전달하는 등의 방법을 사용한다.
- 클라이언트는 전달받은 토큰을 저장합니다.
- 저장하는 위치는 Local Storage, Session Storage, Cookie 등 다양하다.
- 클라이언트가 서버로 리소스를 요청할 때 토큰을 함께 전달한다.
- 토큰을 보낼 때에도 Authorization 헤더를 사용하거나 쿠키로 전달할 수 있다.
- 서버는 전달받은 토큰을 서버의 비밀 키를 통해 검증한다.
이를 통해 토큰이 위조되었는지 혹은 토큰의 유효 기간이 지나지 않았는지 등을 확인할 수 있다.
- 토큰이 유효하다면 클라이언트의 요청에 대한 응답 데이터를 전송한다.
.
으로 나누어진 세 부분이 존재하며 각각을 Header
, Payload
, Signature
라고 부른다.Header
에는 마치 HTTP의 헤더처럼 해당 토큰 자체를 설명하는 데이터가 담겨 있다.JSON
형태로 작성한다.{
"alg": "HS256",
"typ": "JWT"
}
Payload
는 HTTP의 페이로드와 마찬가지로 전달하려는 내용물을 담고 있는 부분이다.JSON
형태로 담는다.{
"sub": "someInformation",
"name": "phillip",
"iat": 151623391
}
JSON
객체를 base64
로 인코딩하면 JWT의 두 번째 부분인 Payload
가 완성된다.Signature
는 토큰의 무결성을 확인할 수 있는 부분이다.Header
와 Payload
가 완성되었다면, Signature
는 이를 서버의 비밀 키(암호화에 추가할 salt)와 Header에서 지정한 알고리즘을 사용하여 해싱한다.HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);
Signature
는 아래와 같은 방식으로 생성됩니다.Signature
을 사용해서 위조된 토큰을 알아낼 수는 있지만, 토큰 자체가 탈취된다면 토큰 인증 방식의 한계가 드러난다.