반응형
개념정리
Spring Boot JWT 기본개념과 특징
1. 서버 기반 인증 vs 토큰 기반 인증
특정 사용자가 서버에 접근을 했을 때, 이 사용자가 인증된 사용자인지 구분하기 위해서는 여러 방법을 사용할 수 있는데, 대표적인 방법으로는
- 서버 기반 인증
- 토큰 기반 인증
위 2가지 방법으로 나눌 수 있다. 위 방법들은 각각의 장, 단점이 존재하기 때문에 상황에 맞게 적절한 방법을 선택해야합니다. 그 중 JWT는 '토큰 기반 인증'에 해당하는 방법입니다.
토큰을 사용한다는 것은 요청과 응답에 토큰을 함께 보내 이 사용자가 유효한 사용자인지를 검색하는 방법이다. 이때, 보통 Json Web Token(JWT)를 사용해서 토큰을 전달한다.
JWT 동작 방식
- 클라이언트가 아이디와 비밀번호를 서버에게 전달하며 인증을 요청한다.
- 서버는 아이디와 비밀번호를 통해 유효한 사용자인지 검증하고, 유효한 사용자인 경우 토큰을 생성해서 응답한다.
- 클라이언트는 토큰을 저장해두었다가, 인증이 필요한 api에 요청할 때 토큰 정보와 함께 요청한다.
- 서버는 토큰이 유효한지 검증하고, 유효한 경우에는 응답을 해준다.
2. 토큰 사용 방식의 장단점
장점
- 보안 이슈
사용자가 자신의 비밀 값으로 서버에 로그인하게 되면, 서버는 JWT를 리턴한다. token을 인증 값으로 사용하게 되면 기존 쿠키/세션을 사용하는 방식보다 많은 보안 이슈를 막을 수 있다. 서버는 GUI로부터 받은 JWT가 유효할 경우, resource를 사용하도록 허용한다. 또한 JWT는 쿠키를 사용하지 않기 떄문에, Cross-Origin Resource Sharing (CORS) 이슈가 발생하지 않는다.- 무상태성 : 사용자의 인증 정보가 담겨있는 토큰을 클라이언트에 저장하기 때문에 서버에서 별도의 저장소가 필요 없어, 완전한 무상태(stateless)를 가질 수 있습니다. 그리고 이로인해 서버를 확장할 때 용이하다.
- 확장성 : 토큰 기반 인증을 사용하는 다른 시스템에 접근이 가능하다. (ex. Facebook 로그인, Google 로그인)
- 무결성 : HMAC(Hash-based Message Authentication) 기법이라고도 불리며, 발급 후의 토큰의 정보를 변경하는 행위가 불가능하다. 즉, 토큰이 변조되면 바로 알아차릴 수 있다.
- 데이터 용량 : JWT는 기존의 XML보다 덜 복잡하고 인코딩 된 사이즈가 작다. 따라서 HTTP와 HTML 환경에서 사용하기 좋다.
- 사용성 : JSON parser는 대부분의 프로그래밍이 지원하기 때문에 XML을 사용하는 SAML 보다 만들기 쉽다.
- CORS (Cross-Origin Resource Sharing) 문제 때문에 주로 쓴다.
- 보안성 : 클라이언트가 서버에 요청을 보낼 때, 쿠키를 전달하지 않기 때문에 쿠키의 한계점을 극복할 수 있다.
Sesstion의 한계
- 서버 확장 시 세션 정보의 동기화 문제
- 서버가 스케일아웃 돼서 여러 개가 생기면 각 서버마다 세션 정보가 저장. 로그인시(서버1), 새로고침(서버2)로 접근하면 서버는 인증이 안됐다고 판단
- 서버 / 세션 저장소의 부하
- 웹 / 앱 간의 상이한 쿠키-세션 처리 로직
단점
- Self-contained : 토큰 자체에 정보를 담고 있으므로 양날의 검이 될 수 있다.
- 토큰 길이 : 토큰의 페이로드(Payload)에 3종류의 클레임을 저장하기 때문에, 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.
- Payload 인코딩 : 페이로드(Payload) 자체는 암호화 된 것이 아니라, BASE64로 인코딩 된 것입니다. 중간에 Payload를 탈취하여 디코딩하면 데이터를 볼 수 있으므로, JWE로 암호화하거나 Payload에 중요 데이터를 넣지 않아야 한다.
- Stateless : JWT는 상태를 저장하지 않기 때문에 한번 만들어지면 제어가 불가능하다. 즉, 토큰을 임의로 삭제하는 것이 불가능하므로 토큰 만료 시간을 꼭 넣어주어야 한다.
- Tore Token : 토큰은 클라이언트 측에서 관리해야 하기 때문에, 토큰을 저장해야 합니다.
3. JWT 구성
JWT는 .을 기준으로 헤더(header) - 내용(payload) - 서명(signature)으로 이루어져있다.
3-1. 헤더(header)
헤더는 토큰의 타입과 해싱 알고리즘을 지정하는 정보를 포함한다.
- typ : 토큰의 타입을 지정합니다. JWT라는 문자열이 들어가게 된다.
- alg: 해상 알고리즘을 지정합니다.
{
"typ": "JWT",
"alg": "HS256"
}
위 예제를 해석하면, JWT 토큰으로 이루어져있고, 해당 토큰은 HS256으로 해상 알고리즘으로 사용되었다는 것을 알 수 있다
3-2. 정보(payload)
토큰에 담을 정보가 들어갑니다. 정보의 한 덩어리를 클레임(claim)이라고 부르며, 클레임은 key-value의 한 쌍으로 이루어져있다. 클레임의 종류는 세 종류로 나눌 수 있다.
- 등록된(registered) 클레임
- 토큰에 대한 정보를 담기 위한 클레임들이며, 이미 이름이 등록되어있는 클레임
- iss : 토큰 발급자(issuer)
- sub : 토큰 제목(subject)
- aud : 토큰 대상자(audience)
- exp : 토큰의 만료시간(expiraton). 시간은 NumericDate 형식으로 되어있어야 하며,(예: 1480849147370) 항상 현재 시간보다 이후로 설정되어있어야한다.
- nbf : Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념. NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않는다.
- iat : 토큰이 발급된 시간 (issued at)
- jti : JWT의 고유 식별자로서, 주로 일회용 토큰에 사용한다.
- 공개(public) 클레임
- 말 그대로 공개된 클레임, 충돌을 방지할 수 있는 이름을 가져야하며, 보통 클레임 이름을 URI로 짓는다.
- 비공개(private) 클레임
- 클라이언트 - 서버간에 통신을 위해 사용되는 클레임
→ 예제 Payload
{
"iss": "ajufresh@gmail.com", // 등록된(registered) 클레임
"iat": 1622370878, // 등록된(registered) 클레임
"exp": 1622372678, // 등록된(registered) 클레임
"https://shinsunyoung.com/jwt_claims/is_admin": true, // 공개(public) 클레임
"email": "ajufresh@gmail.com", // 비공개(private) 클레임
"hello": "안녕하세요!" // 비공개(private) 클레임
}
3-3. 서명(signature)
해당 토큰이 조작되었거나 변경되지 않았음을 확인하는 용도로 사용하며, 헤더(header)의 인코딩 값과 정보(payload)의 인코딩값을 합친 후에 주어진 비밀키를 통해 해쉬값을 생성한다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
4. JWT 로그인의 이해
- JWTAuthFilter : API 요청 Header 에 전달되는 JWT 유효성 인증
- 모든 API 에 대해 JWTAuthFilter 가 JWT 확인
- 로그인 전 허용이 필요한 API 는 예외처리 필요 ⇒ FilterSkipMatcher
- ex) 로그인 폼 페이지, 로그인 처리, css 파일 등
- FormLoginFilter : 회원 폼 로그인 요청 시 username / password 인증
- 인증 성공 시 응답 (Response) 에 JWT 포함
- JWT 전달방법은 개발자가 정함
- 예) 응답 Header 에 아래 형태로 JWT 전달
- 인증 성공 시 응답 (Response) 에 JWT 포함
**Authorization: BEARER** <JWT>
ex)
**Authorization: BEARER** eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzcGFydGEiLCJVU0VSTkFNRSI6IuultO2DhOydtCIsIlVTRVJfUk9MRSI6IlJPTEVfVVNFUiIsIkVYUCI6MTYxODU1Mzg5OH0.9WTrWxCWx3YvaKZG14khp21fjkU1VjZV4e9VEf05Hok
반응형
'개발 하나둘셋 > Java & Spring' 카테고리의 다른 글
Spring Boot에서 CORS 방법 (0) | 2021.12.13 |
---|---|
Spring Security (0) | 2021.12.11 |
Spring boot에서 AWS S3 파일 업로드 하기 (0) | 2021.12.08 |
[java] 메서드, 파라미터 이해하기 (0) | 2021.12.03 |
오버로딩과 오버라이딩 (0) | 2021.11.26 |