💻 백엔드개발/멋쟁이사자처럼 12기

인증, 인가, JWT, 요청 캐싱

aaahyunseo 2024. 10. 29. 23:53

🛠️인증, 인가, JWT, 요청 캐싱

 

인증

: 신원 자체를 검사하는 것.

  • 유저가 누구인지 확인하는 절차, 로그인
  • 존재하는지 안하는지

인가

: 신원 검증된 유저가 특정 자원에 대한 접근 권한이 있는지 검사하는 것.

  • 접근 권한이 있는지 없는지

 

🪄실패 시 HTTP status code

Bad request (400) = client가 서버에 보낸 요청에 포함된 데이터가 잘못되었을 때. ⇒ DTO에 알맞지 않은 request.

Unauthorized (401) = 인증에 실패했을 때 ⇒ 로그인 실패

Forbidden (403) = 인가에 실패했을 때 ⇒ 권한 없음

Not Found (404) = 해당 리소스를 찾을 수 없을 때 ⇒ 해당 id를 찾을 수 없을 때

Conflict (409) = 리소스를 생성하려는데, 이미 존재할 때

 

🪄성공 시 HTTP status code

OK (200) ⇒ GET, PUSH, PATCH, DELETE

Created (201) ⇒ POST

  • Header에 userId를 넣는 게 잘못된 이유
    1. Header에 유저 id를 넣는 것 자체가 잘못됨
    2. userId가 노출되기 때문
    3. 유저 id가 노출되면 해당 유저인 척 요청을 보낼 수 있음. 근데 이걸 막을 순 없음
    4. 매우 비효율적. 매 요청마다 DB에 쿼리를 사용자가 실제로 존재하는지 검사하는 코드를 작성해야함.

📍HTTP Stateless

: 서버가 클라이언트 상태를 보존하지 않는 것.

  • Connectionless(비연결성)
    • 각 요청이 독립적으로 처리
    • 요청에 맞는 응답을 보낸 후 연결을 끊음
  • Stateless(무상태성)
    • 이전 데이터를 유지하지 않음
    • 요청 시마다 인증 필요
  • 장점 : 서버의 확장성이 높다. → 서버에 상태를 저장하지 않으므로 서버 확장이 용이함.
  • 단점 : 클라이언트가 데이터를 추가 전송해야 한다.
  • RESTful → stateless

📍두 가지 인가 방식

1️⃣ 세션 기반

  • 흐름
  1. 클라이언트 : 사용자가 로그인 화면에서 로그인을 함. → 로그인 정보인 id, password를 서버로 request
  2. 서버 : DB에 저장된 id, password와 입력받은 id, password를 비교
  3. 서버 : 일치 시 session ID 생성 후, session ID, 사용자 정보(id, 이름 등)를 세션 유효기간 등의 정보가 담긴 새로운 세션을 생성. → 이 세션을 서버의 메모리 혹은 세션 스토어에 저장
  4. 서버 : 생성한 session ID를 클라이언트에 header의 Set-Cookie로 전달.
  5. 클라이언트 : 서버로부터 전달받은 session ID를 클라이언트의 쿠키에 저장
  6. 클라이언트 : 서버로 전송하는 모든 요청에 session ID를 쿠키에 담아 전달
  7. 서버 : 클라이언트로부터 받은 session ID와 세션 스토어에 저장되어 있는 session ID 일치 여부 확인
  8. 서버 : 일치 시 해당 session ID에 연결된 세션 정보를 스토어에서 검색
  9. 서버 : 세션 정보를 활용해 해당 유저의 상태나 권한 확인 → 요청에 맞는 작업 수행.
  • 장점
    • 쿠키에 아무런 의미 없는 session ID 값이 저장되므로 쿠키 해석 불가능.
    • 유저의 모든 정보들은 서버에서 관리하기 때문에 안전함. → 유저 ID를 숨길 수 있음.
  • 단점
    • DB를 사용하므로 느림.
    • DB를 In-Memory로 사용할 수도 있음. → 확장성이 좋지 않음(서버 컴퓨터를 추가할 경우 각 서버 컴퓨터마다 세션 정보를 공유 해야 하는 한계)

2️⃣토큰 기반

  • 흐름
  1. 서버가 클라이언트로부터 로그인 요청을 받음
  2. 유저의 로그인 정보가 유효하다면 서버에서 유저의 정보(userId)를 담아 토큰 생성 (토큰은 public함.)
  3. 이 토큰을 클라이언트에 반환
  4. 클라이언트는 서버에 모든 요청마다 토큰을 포함해 요청을 보냄
  5. 서버는 토큰을 뜯어 사용자의 정보를 확인하여 토큰을 검증하고, 요청에 응답
  • 토큰 종류
    • AccessToken : 유저의 기본적인 정보와 만료 시간 등을 담은 토큰
    • RefreshToken : AccessToken이 만료되었을 때, 재발급을 위한 토큰
  • 장점
    • 세션과 달리 DB를 한번 덜 거치기 때문에 좀 더 빠름
    • 세션과 달리 범용적으로 쓰일 수 있음. 확장성이 좋음
  • 단점
    • 세션과 달리 너무 많은 정보를 클라이언트가 보유하게 됨
    • 인증 정보(userId)를 클라이언트에서 관리하기 때문에 취약함

📍JWT(Json Web Token)

  • JWT는 3개의 부분으로 이루어짐.
  1. Header : 암호화에 사용되는 알고리즘 정보→ 토큰을 어떻게 verify 하는지
  2. Payload : 실제로 담을 데이터 → 발급 시간, 만료 시간, 토큰을 통해 공개하기 원하는 내용(userID, name 등)
  3. Signagture : Base64라는 인코딩 방식으로 인코딩한 Header와 Payload 그리고 SECRET CODE를 합친 값.
  • Header랑 Payload는 인코딩만 되고, 따로 암호화되지 않음. ⇒ 누구나 JWT를 까서 Payload를 볼 수 있음.
  • Signature는 SECRET KEY(서버에 존재)를 모르면 복호화 불가능. ⇒ SECRET KEY를 알지 못하는 이상 토큰을 조작할 수 없음.
  • JWT는 만료 시간을 포함할 수 있어서 토큰의 유효성을 관리할 수 있음. ⇒ 보통 AccessToken = 3시간 / RefreshToken = 1달

📍Spring Interceptor

Spring은 HTTP Request, Response가 Controller로 전달되기 전, Controller에 나온 후 해당 HTTP Request, Response를 가로채서 특정 작업을 수행할 수 있는 Interceptor라는 기능 제공.

Interceptor

: 컨트롤러의 핸들러를 호출하기 전이나 후에 요청과 응답을 참조하거나 가공할 수 있는 일종의 필터 역할.

  • 인증해주는 역할. user 인증 완료 시 맞는 객체를 controller로 전달해줌.
  • preHandle() : 컨트롤러가 호출되기 전 실행. → 리턴 값이 true이면 해당 인터셉터 실행 후 핸들러에 접근하고, false인 경우 작업 중단.
  • postHandle() : 컨트롤러 실행 후, view 생성 이전에 실행.
  • aferCompletion() : 모든 작업이 완료된 후에 실행.

🪄JwtTokenProvider 역할

  1. 정보(userId)를 받아 해당 정보를 payload에 담아 jwt token을 발급
  2. jwt token을 받아 복호화해 정보(userId)를 반환

@RequestScope

: Request가 들어와서 Interceptor까지 유지되는 Bean

  • cotroller에서는 유효하지 않음.
  • AuthenticationContext를 controller까지는 못가져감
  • authentication 패키지에 어노테이션을 생성해서 주입해줘야 함.→ArgumentResolver에서 supportParameter , resolveArgument 정의
    • supportsParameter() : 어떤 어노테이션의 기능인지
    • resolveArgument() : 해당 어노테이션의 실제 동작 정의
  • @AuthenticateUser User user

🪄AuthenticationInterceptor 클래스

  1. request에서 access token 추출
  2. token(jwt)에서 payload(userId) 추출
  3. userId를 통해 User 검증, user 추출
  4. AuthenticationContext에 user저장.

Cookie

: 서버에 의해 사용자에 저장되는 정보 → 브라우저가 쿠키에 jwt를 저장

  • key - value 형태
  • key : AccessToken
  • value : Bearer {Jwt}

Header: 서버와 클라이언트가 요청, 응답 시에 정보를 주고 받는 부분(userID 등)

Bearer

Authorization: Bearer {JWT Token}

'💻 백엔드개발 > 멋쟁이사자처럼 12기' 카테고리의 다른 글

git 명령어  (0) 2024.10.30
Cookie와 Header  (0) 2024.10.30
RDB, 데이터베이스 구축, JPA  (0) 2024.10.29
HTTP Request & Response, 예외처리  (0) 2024.10.29
Spring MVC, 컨트롤러, 서비스, Lombok  (0) 2024.10.29