쿠키와 세션
HTTP 에 상태 정보를 유지(Stateful)하기 위해 사용
서버에서는 클라이언트 별로 인증 및 인가를 할 수 있게 됨.
1. 쿠키 (Cookie)
클라이언트에 저장될 목적으로 생성한 작은 정보를 담은 파일 입니다.
브라우저에 저장된 '쿠키' 를 확인해 보죠.
'개발자도구' -> Application -> Storage -> Cookies
2 세션 (Session)
서버에서 일정시간 동안 클라이언트 상태를 유지하기 위해 사용됩니다.
'세션 ID' 를 부여한 후 클라이언트 별 필요한 정보를 서버에 저장합니다.
'세션 ID' 는 클라이언트의 쿠키값('세션 쿠키' 라고 부름)으로 저장되어 클라이언트 식별

서버는 세션ID 를 사용하여 세션을 유지합니다.
1. 클라이언트가 서버에 1번 요청
2. 세션ID 를 생성하고, 쿠키에 담아 응답 ( ID 형태: "SESSIONID = 12A345" )
3. 클라이언트가 쿠키에 세션ID를 저장 ('세션쿠키')
4. 클라이언트가 서버에 2번 요청(세션 ID 포함)
5. 서버 는 세션ID 를 확인, 1번 요청과 같은 클라이언트임 을 인지.
Cookie vs Session

쿠키 사용법
(근대 이름에 공백이 있으면 안됨)
밑에 것 처럼 공백이 있으면 ㄴㄴ
addCookien
new Cookie(AUTHORIZATION_HEADER, cookieValue);`
- Cookie에 저장될 Name과 Value를 생성자로 받는 Cookie 객체를 생성합니다.
setPath
setMaxAge : Path와 만료시간을 지정합니다.
(Cookie)
public static void addCookie(String cookieValue, HttpServletResponse res) {
try {
cookieValue = URLEncoder.encode(cookieValue, "utf-8").replaceAll("\\+", "%20"); // Cookie Value 에는 공백이 불가능해서 encoding 진행
Cookie cookie = new Cookie(AUTHORIZATION_HEADER, cookieValue); // Name-Value
cookie.setPath("/");
cookie.setMaxAge(30 * 60);
// Response 객체에 Cookie 추가
res.addCookie(cookie);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage());
}
}
쿠키 읽기
@GetMapping("/get-cookie")
public String getCookie(@CookieValue(AUTHORIZATION_HEADER) String value) {
System.out.println("value = " + value);
return "getCookie : " + value;
}
Session 활용
Servlet에서는 유일무이한 '세션 ID'를 간편하게 만들수 있는 HttpSession을 제공 해줍니다.
1. HttpSession 생성
@GetMapping("/create-session")
public String createSession(HttpServletRequest req) {
// 세션이 존재할 경우 세션 반환, 없을 경우 새로운 세션을 생성한 후 반환
HttpSession session = req.getSession(true);
// 세션에 저장될 정보 Name - Value 를 추가합니다.
session.setAttribute(AUTHORIZATION_HEADER, "Robbie Auth");
return "createSession";
}
HttpServletRequest를 사용하여 세션을 생성 및 반환
req.getSession(true) : 세션이 존재할 경우 세션을 반환하고 없을 경우 생성합니다.
( 반환된 세션은 브라우저 Cookie 저장소에 ‘JSESSIONID’라는 Name으로 Value에 저장됩니다. )
2. HttpSession 읽기
@GetMapping("/get-session")
public String getSession(HttpServletRequest req) {
// 세션이 존재할 경우 세션 반환, 없을 경우 null 반환
HttpSession session = req.getSession(false);
String value = (String) session.getAttribute(AUTHORIZATION_HEADER); // 가져온 세션에 저장된 Value 를 Name 을 사용하여 가져옵니다.
System.out.println("value = " + value);
return "getSession : " + value;
}
req.getSession(false) : 세션이 존재할 경우 세션을 반환하고 없을 경우 null을 반환합니다.
session.getAttribute(”세션에 저장된 정보 Name”) : Name을 사용하여 세션에 저장된 Value를 가져옵니다.
JWT란 무엇일까?
JWT(Json Web Token)
사용자에 대한 속성을 저장하는 Claim 기반의 Web Token
쿠키 저장소를 사용하여 JWT를 저장
1. 서버가 1대인 경우

Session1 이 모든 Client의 로그인 정보를 소유하고 있습니다.
2. 서버가 2대 이상인 경우
( 대용량 트래픽 처리를 위해 서버 2대 이상 운영이 필요할 수 있습니다. )

Session 마다 다른 Client 로그인 정보를 가지고 있을 수 있습니다.
- Session1: Client1, Client2, Client3
- Session2: Client4
- Session3: Client5, Client6
만약 로그인 정보를 가지고 있지 않은 서버에 에 API 요청을 하게되면 문제가 발생하지 않을까?
해결방법 은 :
Sticky Session: Client 마다 요청 Server 고정.
세션 저장소 생성하여 모든 세션을 저장합니다.

3. JWT 사용
로그인 정보를 Server 에 저장하지 않고,
Client 에 로그인 정보를 JWT 로 암호화하여 저장 → JWT 통해 인증/인가

모든 서버에서 동일한 Secret Key 소유합니다
Secret Key 통한 암호화 / 위조 검증 (복호화 시).

Pros :
동시 접속자가 많을 때 서버 측 부하 낮춤
Client, Sever 가 다른 도메인을 사용할 때 ( 카카오 OAuth2 )로그인 시 JWT Token 사용.
Cons :
구현의 복잡도 증가
JWT 에 담는 내용이 커질 수록 네트워크 비용 증가
생성된 JWT 를 일부만 만료.
Secret key 유출 시 JWT 조작 가능.
JWT 사용 흐름
1 client 가 username,password 로그인시.
1.1 서버에서 "로그인 정보" → JWT 로 암호화 (Secret Key 사용)

1.2 서버에서 직접 쿠키를 생성해 JWT를 담아 Client 응답에 전달
JWT 전달방법은 개발자가 정함
( 응답 Header에 아래 형태로 JWT 전달 )
Cookie cookie = new Cookie(AUTHORIZATION_HEADER, token); // Name-Value
cookie.setPath("/");
token 에 토근값을 넣으면 됨.
2 클라이언트 에서 JWT 인증방법
( 서버에서 API 요청 시마다 쿠키에 포함된 JWT를 찾아서 사용 )
2.1 서버에서 API 요청 시마다 쿠키에 포함된 JWT를 찾아서 사용
public String getTokenFromRequest(HttpServletRequest req) {
Cookie[] cookies = req.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(AUTHORIZATION_HEADER)) {
try {
return URLDecoder.decode(cookie.getValue(), "UTF-8"); // Encode 되어 넘어간 Value 다시 Decode
} catch (UnsupportedEncodingException e) {
return null;
}
}
}
}
return null;
}
쿠키에 담긴 정보가 여러 개일 수 있기 때문에
그 중 이름이 JWT가 담긴 쿠키의 이름과 동일한지 확인하여 JWT를 가져옵니다.
2.2 Server
2.2.1 JWT 위조 여부 검증 (Secret Key 사용).
2.2.2 JWT 유효기간이 검증
2.2.3 검증 성공시 → JWT → 에서 사용자 정보를 가져와 확인
( ex) GET /api/products : JWT 보낸 사용자의 관심상품 목록 조회 ).
JWT 구조.
JWT 는 누구나 평문으로 복호화 가능합니다.
하지만 Secret Key 가 없으면 JWT 수정 불가능합니다.
JWT 는 Read only 데이터
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
Payload에 실제 유저의 정보가 들어있고, HEADER와 VERIFY SIGNATURE부분은 암호화 관련된 정보 양식이라고 생각하시면 됩니다.
'Spring' 카테고리의 다른 글
| Spring 숙련 4 (회원가입 만들기) (0) | 2024.01.25 |
|---|---|
| Spring 숙련 3 (JWT 다루기) (1) | 2024.01.24 |
| Spring 숙련 1 (Bean을 수동)(복수Bean 타입)(인증 과 인과) (6) | 2024.01.24 |
| Spring 기초 11(마지막) (Spring Data JPA 의 Query Methods) (0) | 2024.01.21 |
| Spring 기초 10 (JPA Auditing (시간 받기)) (0) | 2024.01.21 |