SPRING

1. 인증 방법 - 쿠키,세션,jwt

개발하는고양이 2023. 12. 23. 16:41
반응형

인증

유저가 서비스의 회원임을 확인하는 것을 인증(Authentication) 이라고 한다.
인증된 유저만이 특정 기능을 사용하도록 하는것을 인가(Authorization) 라고 한다.

 

유저가 회원가입을하고, 로그인을 해서 자신이 관심있는 회사를 조회한다고 가정해보자.
로그인된 유저만이 관심회사 조회 기능을 쓸수 있다고 한다.

유저를 인증 한 뒤, 해당 기능에 대해 유저를 인가하면 될것같다.

 

그렇다면 인증을 어떻게 해야할까?

아이디와 비밀번호를 생성해서 디비에 저장하고, 유저가 아이디와 비밀번호를 쳤을때 일치하면 보내주면 되지 않나?

웹 사이트는 HTTP 통신 위에서 동작한다. 따라서 웹 사이트 내의 모든 요청과 응답은 stateless하다.

(서버에서 Client의 이전 상태를 기억못함.)

->  반복적으로 ID/PW를 입력해야 한다.
-> 디비 털리면 끝이다.

 

위의 방법 말고

인증에는 3가지 방법이 있다.

Cookie

HTTP 쿠키 서버가 웹 브라우저에 전송하는 작은 데이터 조각이다. 브라우저는 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재요청 시 저장된 데이터를 함께 전송한다. ( 저장된 데이터라 함은, 장바구니, 구글테마 이런 개인의 정보들)
쿠키는 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용하며, 이를 통해 사용자의 로그인 상태를 유지할 수 있다.
최초로 로그인을 하고 나면 쿠키가 발행되므로 유저가 직접 매 요청마다 id,pw를 날릴필요가 없는것이다.

 

쿠키 사용 시 단점
1. 노출
쿠키는 노출되었을 때 즉, 외부에서 패킷을 잡아 세션을 뜯어본다면
id,pw 정보를 볼 수 있다. 
그렇다는 것은 조작 또한 가능성이 있다는 뜻이다.
2. 브라우저마다 지원 형태 상이함
따라서 다른 브라우저간에 공유가 불가능하다.
3. 사이즈 제한
충분한 데이터를 담을 수 없는 경우가 있다. (4KB)
4. 서버는 매번 id,pw를 받아서 인증을 해야하는 번거로움.

Session

쿠키가 노출되었을 때 단점을 보완하고자 나온 기술이 바로 세션이다.
세션 또한 정보를 주고받는다는 방식은 같다.
쿠키는 민감한 정보(id,pw)를 직접 주고 받지 않고 인증 정보 (=세션id)자체를
특정 세션 저장소에 저장한다.
이 값을 쿠키에 넣어서 클라이언트가 쿠키를 요청할 때마다 세션 저장소에 있는 정보랑 일치하는지 확인하는 방식이다. 
쿠키 + 세션 인증 과정

 

이 방식은 쿠키가 털려도 세션id만 나와있지 유저의 id,pw는 없다.
물론 세션id를 볼 수 있지만, 현재 저장된 세션 저장소를 모두 지워버리면 된다. (인증 수단 제거)
하지만 정상적으로 이용중이던 사용자까지 피해를 본다.

또한, stateless를 위배한다. 왜냐하면 서버의 세션 저장소에 세션id인 상태를 저장하는 것이기 때문이다. = stateful
stateful하면 뭐 어떠냐 할 수 있지만, 서버에 상태를 저장해야하므로, 해당 서버를 늘린다면 따로 세션id를 또 저장해야한다.

 

세션 사용시 단점
1. 추가적인 비용
세션id를 위한 저장소가 있어야한다. 또한 이 저장소에 문제가 생기면 다른 유저들까지도 인증이 불가하다.
2. 매번 저장소 조회
요청마다 세션 저장소를 조회해햐한다.
3. stateful
http의 장점을 발휘하지 못하고 scale out에 방해된다.
4. 보안
세션id를 탈취하여 해당 세션id로 서버에 요청을 보내서 인증된 클라이언트인 척 할 수 있다.
솔직히 쿠키를 보완해서 나왔다고 하는데, 디비도 조회해야하고  보안도 딱히.... 별로인듯?

JWT 

Json Web Token 
인증에 필요한 정보들을 토큰에 담아 암호화시킨 인증 방식이다.

 

header

{
    "type":"jwt",
    "alg":"HS512"
}

 

payload

Claim이라는 사용자또는 토큰에 대한 property를 저장한다.

{
"iss":"jrnecki",
"sub":"a1",
"exp":192949494
}

key-value 구조로 저장하는데, key에 대해서 알아보자.
1. iss:  토큰 발급자
2. sub: 토큰 제목 - 사용자에 대한 식별값!
3. aud: 토큰 대상자
4. exp: 토큰 만료 시간
5. nbf: 토큰 활성 날짜(Not Before 이전의 날짜에는 활성화 되지 않음!)
6. iat: 토큰 발급 시간
7. jti: jwt 토큰 식별자(issuer가 여러명일 때 이를 구분하도록)
꼭 이 7가지를 포함해야되는 것은 아니다. 또한 이외에도 필요한 것은 추가하면된다.

주의할점은, 민감한 정보를 담으면 안된다. header와 payload는 단순히 인코딩(base64)되어 있을 뿐, 디코딩하면 값을 알아내기 때문에.

 

siganture

header(encoding)+payload(encoding) =secretkey => hash 생성

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

hash => base64인코딩 즉, 문자열 인코딩이 아닌 hex -> base64

secretkey는 서버에 있는 개인키로만 암호를 풀 수 있다.
1. jwt토큰을 클라이언트가 서버로 전달
2. 서버는 secretkey로 signature 복호화
3. 복호화된 signature에서 인코딩된 header와 payload 각각 일치한지 확인

 

jwt 사용시 장점
1. 인증 저장소 불필요
2. 상태 저장 불필요
3. 보안
4. 공통 스펙

반응형

'SPRING' 카테고리의 다른 글

3. 인증 관련 구조와 내부 동작  (1) 2023.12.23
2. Spring Security란?  (1) 2023.12.23
Packaging Jar VS War  (0) 2023.12.07
빌드 도구 Maven VS Gradle  (1) 2023.12.07
자바,스프링,스프링부트 간단한 개념과 차이점  (1) 2023.12.07