JWT(Json Web Token)
JWT란 Json 객체로 안전하게 전송하기 위한 방식이다. 이 정보는 디지털 서명이 되어 있으므로 신뢰할 수 있다.
보통 HMAC 알고리즘이나 RSA 알고리즘을 사용하여 암호화를 한다.
핵심은 서명된 토큰이라는 점이고, 내가 쓴게 맞다! 라는 의미로 사용한다.
서명된 토큰은 그 안에 포함된 클레임(정보)의 무결성을 확인할 수 있게 해준다.
JSON은 Base64URL로 인코딩되어 있다. Base64URL은 암호화를 하고, 복호화를 할 수 있게 해주는 방법이다. (해시랑 다른 것이다. 예를 들어 비밀번호를 데이터베이스에 저장할 때는 해시 함수를 이용하여 암호화를 해주기 때문에 암호화된 데이터로는 원래의 비밀번호가 어떤건지 알 수 없다. -> 그래서 비밀번호 찾기에서 비밀번호를 알 수는 없는 것이다. )
그러니까 사실 이상하게 적혀있긴 하지만 Header와 payload에 대한 정보는 사실 그냥 디코딩만 하면 알 수 있다. (Base64 URL을 통해 디코딩)
JWT의 핵심은 signature이다.
JWT의 구조는 xxxx.yyyy.zzzz -> 헤더, payload, signature로 구성되어 있다.
signature은 헤더 + payload + 개인키 를 HMAC(HS256)으로 암호화한 것이다.
헤더에 들어가는 정보
- 사용중인 알고리즘
- 토큰 유형(JWT)
payload에 들어가는 정보
- 클래임
- 등록된 클레임 : 필수 조건은 아니지만 권장되는 미리 정의된 클레임(발행자, 주체, 청중..)
- 개인 클레임 : 유저아이디 같은 정보를 넣을 수 있다. 유저를 특정할 수 있는 것을 개인 클레임에 보통 넣는다.
secret키는 서버만 알고 있는 키이다. 클라이언트가 username으로 tae77777을 보내고 비밀번호로 1234를 보낸다고 생각해보자. 그리고 secret키가 'secret'이라고 했을 시 아래와 같다. 여기서 signature만 HS256으로 암호화를 한 뒤에 Base64로 인코딩을 하게 되는 것이다. HS256 방식은 HMAC 방식과 SHA256방식을 합해서 말한 것으로 시크릿 키를 포함한 암호화 방식이다.
중요한 점은 복호화 할 수 없다 는 점이다.
JSON web token을 client는 보통 local Storage에 넣어둔다. 이후에 클라이언트가 서버에 요청할 때 JWT를 실어서 요청하면 서버가 JWT가 신뢰할 수 있는 token인지 확인한다.
그럼 서버에서는 JWT 토큰에 대해서 어떻게 검증할까? -> Signature에 HS256으로 암호화된 정보가 유효한지 알아야 한다.
일단, JWT를 받으면 Header와 Payload를 알 수 있다. 그럼 Base64URL로 인코딩된 header와 Base64URL로 인코딩된 payload와 secret key를 한번에 HS256으로 암호화를 한다. 그럼 클라이언트에게서 받은 JWT의 signature부분을 Base64URL로 복호화해서 같은지 비교해서 인증한다.
-> 인증이 되면 payload에 있는 user 정보를 통해서 DB에서 select해서 돌려주면 된다.
이 방법은 비밀번호를 저장할 때도 같은 방식이다!
세션과 JWT 토큰
Http는 stateless인데 stateful처럼 쓰기 위해서 세션을 만들고 쿠키를 만든다. 쿠키는 동일 도메인에서만 요청이 올 때 발동한다. (CSRF)
쿠키와 세션은 http의 장점인 stateless를 벗어나는 stateful하게 되는 것이다. 즉 서버에 상태를 저장한다. 서버가 한 대일때는 세션과 쿠키에 별다른 단점이 없다. 세션의 문제는 서버가 여러 개가 생길 때 문제가 생긴다.
만약 서버를 scale out하여 개수를 늘린다면 서버마다 세션에 대한 정보를 공유하여야 사용자를 확인할 수 있다. 그럼 결국 중앙 세션 저장소를 반드시 만들어야 한다.
Security Config 작성
Security Filter Chain은 다른 Filter보다 무조건 먼저 작동한다. 그리고 Jwtfilter는 Security 동작전에 실행되어야 한다.
http Basic 방식 : 매번 요청할 때마다 ID와 Password를 다 알고 요청하게 된다. -> 쿠키, 세션을 만들 필요가 없다.
-> ID, pw가 중간에 노출될 수 있기 때문에 https서버를 사용해야 한다.
우리가 쓰려는 방식은 Bearer 방식이다.
: Authorization에 token을 넣는 방식. -> 노출되어도 얘 자체가 ID, PW가 아니기 때문에 위험부담이 적다.
이런 방식이 http Bearer방식이다.
'백엔드' 카테고리의 다른 글
GithubAction을 이용해서 Spring 프로젝트 CI/CD(with Docker) (0) | 2023.09.06 |
---|---|
세션 (0) | 2023.08.25 |
[AWS] Elastic BeanStalk 배포와 Trouble Shooting (0) | 2023.05.23 |
[Spring] Spring으로 웹 개발을 진행할 때 알아야할 정보 (0) | 2023.05.23 |
Gradle (0) | 2022.12.27 |