My Melody Is Cute Spring Security JWT 인증
본문 바로가기

개발공부🌷/Spring Security

Spring Security JWT 인증

💖세션 기반 인증

  • 서버 or DB에 인증된 사용자의 정보를 세션 형태로 세션 저장소에 저장하는 방식
  • 인증된 사용자의 상태를 유지하기 위한 전통적인 방식 (사용자의 고유세션ID가 클라이언트의 쿠키에 저장되어 인증수단으로 사용)
  • 상대적으로 적은 네트워크 트래픽 사용(세션 Id만 클라이언트쪽에서 사용)
  • 보안성 측면에서 더 유리 (서버측에서 세션정보를 관리)
  • 서버의 확장성 면에서 세션 불일치 문제가 발생할 가능성이 높음 (인증된 사용자의 request의 상태를 유지해야하기때문)
  • SSR 방식의 애플리케이션에 적합한 방식

 

HTTP 프로토콜의 특징인 비연결성(Connectionless) 비상태성(Stateless)을 보완하여 인증된 사용자의 request의 상태를 유지하기위한 수단이 세션

 

- 세션기반인증 = 서버(혹은 DB)에 유저 정보를 담아 세션값과 일치하는지 확인하는 방식

=> 매번 데이터베이스를 확인해야했는데 이 부담을 클라이언트에 넘겨줄수 없을까?

 


 

💖토큰 기반 인증

  • 토큰에 포함된 인증된 사용자 정보를 서버측에서 별도로 관리하지 않음
  • 사용자 인증 정보가 포함된 토큰을 헤더에 포함시켜서 request 전송시 인증 수단으로 사용
  • 세션에 비해 상대적으로 많은 네트워크 트래픽 사용 ( 토큰 내에 인증된 사용자 정보등을 포함하기 때문)
  • 보안성 측면에서 조금 더 불리 (서버측에서 토큰을 관리하지 않아서)
  • 서버의 확장성 면에서 유리, 세션불일치같은 문제가 발생하지않음( 인증된 사용자 request의 상태를 유지할 필요가 없음)
  • 민감한 정보는 토큰에 포함시키지 말아야함 (토큰에 포함되는 사용자 정보는 토큰 특성상 암호화가 안됨)
  • 토큰이 만료되기 전까지는 무효화되지 않음 ( key/value 쌍의 형태로 저장되는 Redis같은 인메모리 DB에 무효화 시키고자 하는 토큰의 만료 시간을 짧게 주어 해당 토큰을 사용하지 못하게 하는 등의 방법으로 보완)
  • CSR방식의 애플리케이션에 적합한 방식

 

🌟Json Web Token = JWT

Json 포맷으로 사용자에 대한 속성을 저장하는 웹 토큰

데이터를 안전하고 간결하게 전송하기 위해 고안된 인터넷 표준 인증 방식

토큰 인증 방식에서 가장 범용적으로 사용

JSON 포맷의 토큰 정보를 인코딩 후 , 인코딩 된 토큰 정보를 Secret Key로 서명(Sign)한 메시지를 Web Token으로써 인증 과정에 사용   

 

 

1. 액세스 토큰(Access Token)

보호된 정보들(이메일,연락처,사진등)에 접근할 수 있는 권한부여에 사용

처음 인증 받을때(로그인) Access Token과 Refresh Token 둘 다 받지만,

실제로 권한을 얻는데 사용하는 토큰은 Access Token

비교적 짧은 유효기간

( 만료된다면 Refresh Token을 사용해서 새로운 Access Token을 발급받음, 다시 로그인 인증 필요 x)

 

2. 리프레시 토큰(Refresh Token)

Access Token 발급 받을때 사용

긴 유효기간 (사용자의 편의보다 보안이 더 중요한 웹 애플리케이션은 사용하지 않는곳이 많다)

 

🌟JWT의 구조

1. Header

어떤종류의 토큰인지?

어떤 알고리즘으로 Sign 할지?

JSON 객체를 base64방식으로 인코딩하면 첫번째부분 완성

2. Payload

서버에서 활용할 수 있는 유저의 정보(접근권한, 사용자데이터등)

민감한정보(password)는 담지않는것이 좋음

JSON 객체를 base64방식으로 인코딩하면 두번째부분 완성

3. Signature

1,2가 완성되었으면 원하는 비밀 키 (Secret Key) + Header에서 지정한 알고리즘을 사용해서 Header와 Payload에 대해서 단방향 암호화를 수행

토큰의 위변조 유무를 검증하는데 사용

 

ex. HMAC SHA256 알고리즘(암호화 방법중 하나)을 사용한다면 아래와같은 방식으로 Signature 생성

HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload),secret);

 


 

🍀JWT의 장점

1. 무상태성,확장성

서버는 클라이언트정보를 저장할 필요가 없다

클라이언트는 요청때마다 헤더에 토큰을 추가하면 됨

토큰이 만료되기전까진 인증을 한번만 수행

 

2. 안정성

암호화된 토큰 사용

 

3. 어디서나 생성가능

서버가 꼭 만들 필요없음

토큰생성용 서버, 다른 회사에서 토큰관련 작업 맡기기등등

자격증명정보를 직접 관리하지않고 다른 플랫폼의 자격 증명정보로 인증가능 (깃허브,구글등)

 

4. 권한 부여에 용이

토큰의 내용물(Payload) 안에 어떤 정보에 접근 가능한지 정의

ex. 사진,연락처 사용권한부여 / 사진권한만 부여...

 

 

🍀JWT의 단점

1. Payload 디코딩 용이

탈취해서 디코딩후 데이터 확인이 가능하기 때문에 민감한 정보는 포함하면 안됨

 

2. 토큰의 길이가 길어지면 네트워크에 부하를 줄 수 있음

토큰에 저장하는 정보의 양이 많아질 수록 토큰의 길이는 길어지기 때문에

request전송시 마다 긴 토큰 전송하면 네트워크에 부하를 줄 수 있음

 

3. 토큰은 자동으로 삭제되지 않음

또 탈취될 가능성이 있기에 반드시 길지 않은 토큰 만료 기간 추가하기

 

 

🌟토큰 기반 인증 절차 

  • 클라이언트가 서버에 아이디/비밀번호를 담아 로그인요청을 보냄
  • 로그인 인증을 담당하는 Security Filter(JwtAuthenticationFilter)가 클라이언트의 로그인 인증정보 수신 // 1
  • Security Filter가 수신한 로그인 인증정보를 AuthenticationManager에게 전달해 인증처리를 위임 // 2
  • AuthenticationManager가 Custom UserDetailsService(MemberDetailsService)에게 사용자의 UserDetails 조회를 위임 
  • Custom UserDetailsService(MemberDetailisService)가 사용자의 크리덴셜을 DB에서 조회한 후 AuthenticationManager에게 사용자의 UserDetails를 전달 // 3
  • AuthenticationManager가 로그인 인증 정보와 UserDetails의 정보를 비교해 인증처리 
  • JWT 생성 후 클라이언트의 응답으로 전달 // 4

AuthenticationManager대신 처리해주는 부분 제외

나머지(1,2,3,4)는 구현해야함

 


 

 

🌟JWT 적용을 위한 사전 작업

1.의존 라이브러리 추가

JWT를 적용하기위해서 jjwt나 Java JWT같은 라이브러리가 필요함

implementation 'org.springframework.boot:spring-boot-starter-security' 
// (1) Spring Security 적용

// (2) JWT 기능을 위한 jjwt 라이브러리
	implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
	runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
	runtimeOnly	'io.jsonwebtoken:jjwt-jackson:0.11.5'

2. SecurityConfiguration 클래스 추가

3. 회원가입 로직 수정

Dto 회원 인증정보(패스워드필드추가) / Entity 패스워드필드 추가

/ Service 회원등록시 패스워드,권한저장 / CustomAuthorityUtils 클래스 추가 ( Service클래스에 DI하기위해서)

 

🌟JWT 자격 증명을 위한 로그인 인증 구현

사용자의 Username과 Password로 로그인 인증에 성공하면 로그인 인증에 성공한 사용자에게 JWT를 생성 및 발급

1.MemberDetailsservice 클래스 추가 

-Custom UserDetailsService 구현

 

2.LoginDto 클래스 추가

-클라이언트의 Username + password 정보만 담는 단순한 Dto클래스

-로그인 인증정보 역직렬화

-순서는 상관없음

 

3.JwtTokenizer 클래스 추가

-토근 관련 기능을 담는 JWT생성

 

4.JwtAuthenticationFilter클래스 추가(Custom Security Filter)

-로그인 인증요청 처리

 

5. SecurityConfiguration 클래스에 설정추가

-Custom Filter추가를 위해

-JwtAuthenticationFilter를 Spring Security Filter Chain에 추가해서 로그인 인증 처리하도록

 

 

🌟로그인 인증 성공 및 실패에 따른 추가처리

1.AuthenticationSuccessHandler 클래스 추가

-> 로그를 기록 or 로그인에 성공한 사용자 정보를 response로 전송하는 등의 추가 처리

2.AuthenticationFailureHandler 클래스 추가

-> 로그인 인증 실패 시에도 마찬가지로 인증 실패에 대한 추가처리 가능

3. SecurityConfiguration 클래스에 설정 추가

-> AuthenticationSuccessHandler/AuthenticationFailureHandler 추가

단순히 로그만 출력하고있지만 Authentication객체에 사용자 정보를 얻은 후 HttpservletResponse로 출력스트림을 생성하여 Response를 전송할수있다

4. JwtAuthenticationFilter 클래스에 설정추가

-> AuthenticationSuccessHandler 호출 코드 추가

 


 

 

🌟JWT 검증 기능 구현

자격증명이 필요한 request 전송시, request header를 통해 전달받은 JWT를 서버측에서 검증하는 기능 구현

1. JwtVerificationFilter 클래스 추가

- 클라이언트 측에서 전송된 request header에 포함된 JWT 의 검증 작업 수행

- 서버측에서 response header에 JWT를 포함해 전송한 후 클라이언트가 다시 요청보낼때,

그 JWT를 request header에 포함하여 전송할 경우에 서버가 보낸 JWT가 맞는지 검증하는 과정임

 

2. SecurityConfiguration 클래스에 설정추가

- JwtVerificationFilter를 사용하기 위해 세션 정책 설정 - JwtVerification추가

 

1번에서 검증 성공하면 Authentication 객체를 SecurityContext에 저장하는데 stateless특징을 유지하기 위해

세션 유지기간을 아주 짧게(거의 무상태) 주기위해 설정추가

 

3. SecurityConfiguration 클래스 추가

- SecurityConfiguration + 접근권한설정

( SecurityConfiguration클래스는 .anyRequest(0.permitAll() 로 되어있어서 모두 접근 가능)

'개발공부🌷 > Spring Security' 카테고리의 다른 글

Spring Security 1  (0) 2023.12.13