Server/Spring Boot

spring boot // 토큰 기반 / JWT 정보

Jaybon 2020. 8. 6. 17:47

 

아래 사이트를 참고하여 정리합니다

https://velopert.com/2350

 

[JWT] 토큰(Token) 기반 인증에 대한 소개 | VELOPERT.LOG

소개 토큰(Token) 기반 인증은 모던 웹서비스에서 정말 많이 사용되고 있습니다. 여러분이 API 를 사용하는 웹서비스를 개발한다면, 토큰을 사용하여 유저들의 인증작업을 처리하는것이 가장 좋은

velopert.com

 

토큰기반 인증

API를 사용하는 웹서비스를 개발한다면, 토큰을 사용하여 유저들의 인증작업을 처리하는 것이 좋은방법

 

토큰기반 인증 시스템을 선택하는 이유

1. Stateless 서버

Stateful 서버
- 클라이언트에게 요청을 받을 때마다 클라이언트의 상태를 계속유지
- 해당 정보를 서비스 제공에 이용
- ex) 세션을 유지하는 웹서버 - 서버컴퓨터의 메모리 또는 데이터베이스

Stateless 서버
- 상태를 유지 하지 않는다
- 클라이언트측에서 들어오는 요청만으로 작업을 처리
- 클라이언트와 서버의 연결고리가 없기 때문에 서버의 확장성이 높아진다

 

2. 모바일 어플리케이션에 적합
- 안드로이드/ios에서는 쿠키는 이상적이지 않다 (쿠키 컨테이너를 사용해야하는 등)
- 토큰기반은 이 번거로움을 해결할 수 있다

 

3.보안
- 해킹의 위험을 무조건 벗어나는 것은 아니지만 보안을 높일 수 있다

 

토큰기반 인증 시스템을 사용하는 서비스

트위터/ 페이스북/ 깃헙 등

 

토큰을 사용하게 되는 이유

1. 서버기반 인증의 문제점

세션 - 로그인 중인 유저수가 늘어나면 서버의 램이나 데이터베이스의 성능에 무리를 줄 수 있다

확장성 - 트래픽을 감당하기 위해 여러개의 프로세서를 돌리거나, 여러대의 서버 컴퓨터를 추가해야한다. 과정이 복잡해진다.

CORS - 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계 되어있다. 따라서 쿠키를 여러도메인에서 관리하는 것은 번거롭다

 

토큰 기반 시스템의 작동 원리

Stateless 시스템에서 유저의 인증정보를 서버나 세션에 담아 두지 않는다

토큰기반 시스템의 구현방식

1. 유저가 아이디와 비밀번호로 로그인
2. 서버측에서 해당 계정정보를 검증
3. 계정정보가 정확하면 서버->유저 signed 토큰을 발급
4. 클라이언트 측에서 전달 받은 토큰을 저장
5. 요청시마다 토큰을 함께 서버에 전달 (http 요청의 헤더에 토큰값을 포함 시켜 전달)

 

토큰의 장점

무상태(Stateless) + 확장성(Scalability)

서버 확장에 적합(분산 서버라면 어떠한 서버로 요청이 들어가던 상관이 없다)

1. 보안
- 쿠키를 사용함으로 인해 발생하는 취약점이 사라짐(토큰 취약점은 존재)

2. Extensibility 확장성
- Scalability와는 다른 개념
- 로그인 정보가 사용되는 분야를 확장하는 것
- 토큰을 사용하여 다른 서비스에서도 권한을 공유 할 수 있다
(구글 네이버 등의 계정으로 내 사이트에 로그인을 할 수 있는 것처럼)
- 토큰에 선택적인 권한만 부여하여 발급 할 수 있다 (프로필 정보 가져오는 권한 O / 페북에 글쓰는 권한 X)

3. 여러 플랫폼 및 도메인
- 한가지 서비스가 아닌 여러 서비스 및 도메인에서 요청이 정상적으로 처리 된다
- 어플리케이션 응답 부분에 Access-Control-Allow-Origin: * 를 포함시켜서 처리
- 이미지, css, js, html 파일 등은 CDN에서 제공, 서버측에서는 API만 다루도록 설계 가능

아래는 CDN 정보

https://cdn.hosting.kr/cdn%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94/

 

https://cdn.hosting.kr/cdn%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94/

 

cdn.hosting.kr

 

4. 웹 표준 기반

토큰 기반 인증 시스템의 구현체인 JWT는 웹표준에 등록되어있어서 여러 환경에서 지원이 되고 수많은 회사의 인프라스트럭쳐에서 사용 되고 있음

 

-----------------

 

JWT

 

기본정보

두 개체에서 JSON 객체를 사용하여 가볍고 자가수용적인 방식으로 정보를 안전성 있게 전달

1. 수많은 프로그래밍 언어에서 지원됨

2. 자가수용적
- 필요한 모든정보를 자체적으로 지니고 있음
- 토큰의 기본정보 / 전달할 정보 / 토큰 검증 signature

3. 쉽게 전달 가능
- HTTP의 헤더나 URL의 파라미터로 전달 할 수 있음

 

JWT의 사용처

1. 회원인증
- 유저가 로그인 되어 있는지 신경 쓸 필요없이 유저가 요청할 때 토큰만 확인하면 됨
- 세션관리가 필요 없어서 서버 자원을 아낄 수 있음

2. 정보교류
- 두 개체 사이에 안정성 있게 정보를 교환하기에 좋은 방법
- 정보가 sign 되어 있기 때문에 정보를 보낸 이가 바뀌거나 정보가 조작되었는지 검증 가능

 

JWT의 생김새

JWT는 . 으로 구분하여 3가지 문자열로 되어 있음

aaaa.bbbb.cccc

(aaaa는 헤더, bbbb는 내용, cccc는 서명)

JWT 토큰을 만들때는 JWT를 담당하는 라이브러리가 자동으로 인코딩 및 해싱 작업을 해줌

 

헤더

헤더는 두가지 정보를 지니고 있다

typ : 토큰의 타입을 지정한다 (즉 JWT임을 알림)

alg : 해싱 알고리즘을 지정, 보통 HMAC SHA256 또는 RSA가 사용됨, 서명 부분에서 토큰을 검증할 때 사용

{
  "typ": "JWT",
  "alg": "HS256"
}

위 헤더내용을 공백과 엔터를 없애고 base64로 인코딩

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

 

 

정보

payload 라고 하며 토큰에 담을 정보가 들어있음.
정보들 각각을 claim이라고 부름 (name / value 의 한쌍으로 이루어져 있음)

클레임의 종류
1. 등록된(registered) 클레임
- 등록된 클레임의 사용은 선택적이다
- 서비스에서 필요한 정보가 아닌, 토큰에 대한 정보들을 담기 위하여 이름이 정해진 클레임
- iss : 토큰 발급자
- sub : 토큰 제목
- aud : 토큰 대상자
- exp : 토큰의 만료시간 (무조건 현재시간의 이후로 설정해야함)
- nbf : Not Before, 토큰의 활성 날짜와 비슷한 개념, 이 날짜가 되기전엔 토큰이 처리되지 않음
- iat : 토큰이 발급된 시간, 토큰의 age를 판단
- jti : JWT의 고유식별자, 중복적인 처리를 방지하기 위해 사용, 일회용 토큰에 유용

2. 공개(public) 클레임
- 충돌이 방지된 이름을 가지고 있어야함
- 충돌을 방지하기 위해서는 클레임 이름을 URI 형식으로 지어야함

3. 비공개(private) 클레임
- 서버와 클라이언트의 협의하에 사용되는 클레임
- 공개 클레임과는 달리 이름이 중복되어 충돌 될 수 있으니 사용할 때 유의해야함

{
    "iss": "velopert.com",
    "exp": "1485270000000",
    "https://velopert.com/jwt_claims/is_admin": true,
    "userId": "11028373727102",
    "username": "velopert"
}

위 헤더내용을 공백과 엔터를 없애고 base64로 인코딩

eyJpc3MiOiJ2ZWxvcGVydC5jb20iLCJleHAiOiIxNDg1MjcwMDAwMDAwIiwiaHR0cHM6Ly92ZWxvcGVydC5jb20vand0X2NsYWltcy9pc19hZG1pbiI6dHJ1ZSwidXNlcklkIjoiMTEwMjgzNzM3MjcxMDIiLCJ1c2VybmFtZSI6InZlbG9wZXJ0In0

 

 

payload 
- 등록된클레임 - 요청자, 만료시간은 꼭넣자
- 공개된클레임 - URI를 사용
- 비공개클레임 - 비밀번호 이메일 등을 제외한 유저네임, 프라이머리키, 권한 등

토큰에는 패스워드등 중요정보는 넣으면 안된다

 

 

 

라고 한다

 

서명

헤더의 인코딩 값 + 정보의 인코딩 값 + 비밀키로 해쉬

서명부분은 해싱하기 때문에 디코딩이 안됨

 

JWT가 잘 완성 되었는지 검증

https://jwt.io/

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io