Spring Framework/[인프런] Spring Security & OAuth 2.0 & JWT

Chapter 03. 스프링 시큐리티 웹 보안 이해

계란💕 2022. 12. 5. 12:13

 

JWT(Json  Web Token)

  • JWT는 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 컴팩트하고 독립적인 방식을 정의하는 개방형 표준이다.
  • 디지털 서명이 되어 있어서 확인하고 신뢰 가능하다.

 

 

  cf) 세션 클러스터링(session clustering)

  • 두 개 이상의 WAS(Web Application Server)를 사용하는 경우, 로드밸런싱(대용량 트래픽 분산) 또는 Failover(장애 발생 시 예비 시스템으로 전환, 서버 이중화), Auto Scaling(AWS에서 EC2 인스턴스를 자동 생성, 삭제 서비스) 등의 대체된 WAS에개도 동일한 세션을 공유하는 기술

 

참고) https://somida.tistory.com/191

 

 

 

 

 

3.1 세션(Session)이란? 

 

  • 메모리 공유 서버
    • 데이터베이스가 아닌 메모리 공유 서버에서 세션에 대한 정보를 서버끼리 공유한다.
    • 메모리 공유 서버를 써야 I/O가 일어나지 않는다.
    • 메모리 공유 서버에는 HDD 없이 RAM만 있다.
    • I/O(하드디스크 접근하면 풀스캔해야하기 때문에  속도가 100만 배 느려진다.)가 일어나지 않아서 속도가 빠르다.
    • 클라이언트가 어느 서버로 가든지 모든 서버는 하나의 메모리 공유 서버에 접근해서 세션 값에 대한 정보를 확인한다.
    • 메모리 공유 서버에 세션 ID가 모두 저장되니까 관리가 편리하다.
    • ex) Redis 서버

 

 

세션(session) 용도

  • 사용자를 인증할 수 있다.
  • 사용자의 민감 정보를 관리한다.

 

 

로드 밸런싱

  • 서버 부하를 분산시킨다.
  • ex) 동시 접속자가 300명인 경우 최대 100명까지 접속 가능한 서버 세 개를 만든다.

 

 

세션 생성과 소멸 과정

  • 사용자가 request하면 네이버에 접속한다.
    • 네이버(서버)에 최초 접속하면 네이버가 세션이라는 저장소에 사용자에 대한 세션 ID를 생성한다. (집에 들어갈 수 있는 카드키같은 느낌)
    • 각 세션 ID에 대한 작은 저장소(민감 정보가 있다.)가 함께 생긴다. 
    • 서버(네이버)는 response로서 세션 ID를 클라이언트에 돌려준다.
  • 쿠키에 세션 ID가 담긴다.
  • 두번째 접속 부터는 세션 ID를 가지고 네이버에 접속한다. 
  • 로그인 요청하면 세션 ID에 연결된 저장소에 사용자의 정보를 저장한다.
  • 네이버 메인 페이지로 이동한다.
  • 클라이언트(세션 ID를 들고온다)가 서버에  유저 정보를 요청하면?
    • 서버는 세션에서 일치하는 세션 ID, 세션 ID에 연결된 저장소를 확인한다.
  • 서버는 데이터베이스에서 사용자 정보에 대한 응답을 받는다.
    • 이 정보를 클라이언트에 보내준다.

 

 

세션 값이 서버에서 사라지는 경우

  • 서버(ex. (네이버) )에서 세션을 강제로 날린다. 
  • 사용자가 브라우저를 모두 종료한다.
  • 특정 시간(보통 30분)이 지나는 경우

 

 

3.2 TCP(Transmission Control Protocol, 전송 제어 프로토콜)란? 

참고)  https://oranthy.tistory.com/211

 

 

3.3 CIA(Confidential Integrity Availity)란? 

 

CIA(confidential integrity availity)

  • 보안 유지를 위한 3가지
  • confidential(기밀성): 문서 암호화한다.
  • integrity(무결성) 
  • availitity(가용성)
    • 해커가 문서 획득하면 가용성이 깨졌지만  암호화를 못 하는 경우, 기밀성은 유지된다.

 

 

보안 이슈

  • 열쇠 전달 문제 (통신)
  • 문서가 누구로부터 왔는지 (인증)
  • 문서 위조 여부

 

 

3.4 RSA (Ronald Shamir Adleman) 란? 

 

RSA(Ronald Shamir Adleman)

  • Public Key(공개키): 공개해도 상관없는 key
    • 공개키로 잠그는 것 => 암호화
  • Private Key(개인키): 공개하지 않고 개인이 소유한다.
    • 개인키로 잠그는 것 => 전자 문서(서명)
  • 송신자(A), 수신자(B) 모두 각각 다른 공개키, 개인키가 있다. => 비대칭키 기반 암호화
  • A
  • ex) 만약 B가 A에게 메시지를 보내고 싶은 경우? A의 공개키암호화한다. A의 개인키로 복호화 가능, 따라서 A만 열 수 있다.
  • ex) A가 B에게 메시지를 보내고 싶은 경우? B의 공개키로 암호화해서 전달한다.  오직 B의 개인키로만 복호화 가능하다.
    • 그런데 중간에 해커가 탈취할 수도 있으니까 A의 개인키로 한 번 더 암호화한다.
    • B: 문서를 받으면?
      • A의 공개키로 열어본다. 열리면? 인증 완료 (안 열리면, 인증이 안 된 것이다.)
      • B의 개인키로 열어본다.  암호화

 

 

3.5 RFC 문서란? 

RFC(Request for Comments)문서란?

  • 비평을 기다리는 문서라는 뜻이다. 컴퓨터 네트워크 공학 등에서 인터넷 기술에 적용 가능한 새로운 연구, 혁신, 기법 등을 아우르는 메모를 나타낸다.
  • ex) JWT RFC https://www.rfc-editor.org/rfc/rfc7519

 

 

 

JWT(Json Web Token)

  • RSA, HMAC(어떤 시크릿 키를 포함한 암호화 방식) SHA256(해시 - 복호화할 수 없는 키 값을 만든다.), ECDSA 암호화를 이용한다. HS256을 RSA보다 많이 사용한다.
  • header(헤더): 어떤 암호화 알고리즘을 사용했는지, 토큰의 타입
    • Base64Url로 인코딩되어서 JWT의 첫 번째 부분을 형성한다.
    • 헤더에는 HS256 으로 서명
  • payload(패이로드): 토큰에 대한 정보
    • 등록된 클래임(필수는 아니지만 권장되는 미리 정의된 클레임 집합이다. (ex 발행자, 만료 시간, 주제, audience, ...)
    • 개인 클래임(userId 처럼 유저를 특정할 수 있는 PK 값을 넣는다.) 
  • signature(서명): header와 payload에 대해  HMAC을 이용해서 암호화한다.
  • ex)
    • header: HS256 
    • payload: {username: ssar}
    • signature: {header + payload + (서버만 알고 있는 시크릿 키 값)} 를 HS256으로 암호화한다.
    • 서버는 위 세개를 각각 Base64로 인코딩해서 클라이언트에 돌려준다.
    • 클라이언트는 자신의 개인 정보를 달라고 서버에 JWT를 보낸다.
    • 그럼 서버는? 유저의 정보를 {header + payload + (서버만 알고 있는 시크릿 키 값)} 를 HS256으로 암호화해서 클라이언트가 보낸 정보와 확인해서 인증을 완료한다.
    • 그러고 나서 DataBase에서 username을 SELECT해서 보여준다.
  • JWT는 세션 저장소처럼 사용 가능한다.

 

 

 

JWT 요약

  • 서버는 공개키와 개인키가 있다.
  • 서버가 개인키로 {header +payload, 시크릿 키는 없다.}를 잠가서 signature를 만든다. 
  • 서버가 클라이언트에게 이 토큰을 준다.
  • 클라이언트는 그 토큰을 가지고 서버에 보내서 내 정보를 달라고 요청한다. 
  • 서버는 공개키로 signature을 검증하기만 하면 된다.

 

 

yml 파일 세팅

<hide/>
server:
  port: 8080
  servlet:
    context-path: /
    encoding:
      charset: UTF-8
      enabled: true
      force: true
      
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security?serverTimezone=Asia/Seoul
    username: cos
    password: cos1234

  jpa:
    hibernate:
      ddl-auto: update #create update none
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true

 

 

 

 

 

 

 

출처 - https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0/dashboard