Spring Security를 개발하기위해 해당 관련 정보들을 학습하는도중 

일반적으로 사용되는 filer의 두가지에 대해 정리하려고 한다.

- AbstractAurhenticationProcessingFilter
- OncePerRequestFilter

 

 


포스트의 내용의 흐음은 아래와 같다.
  • 두가지 필터의 간단한 내용 요약
  • 차이점 
  • 결론

 

 

 

AbstractAurhenticationProcessingFilter


 

AbstractAurhenticationProcessingFilter를 매번 이름을 쓰기에는 너무 길기 때문에 AAPF로 명명하겠다

 

AAPF는  Spring Security에서 제공하는 기본 인증처리 필터이다

 

 

AAPF의 처리방식간단하게 정리하면 아래순서와 같다

  1. 사용자의 인증을 처리
  2. 인증의 처리가 성공된 경우 → Authentication 객체를 생성
  3. SecurityContextHolder에 생성된 Authentication의 정보를 저장한다

 

처리하는 로직? 상황? 을 통해 사용할 수 있는 방식도 정리해둔다!

  • 인증처리 → Authentication 객체 생성
  • 인증처리 실패 → AuthenticationFailureHandler를 이용해 실패처리를 수행할 수 있다. 
  • 인증처리 성공 → AuthenticationSuccessHandler를 이용해 성공처리를 수행할 수 있다

 

 

 

OncePerRequestFilter

 

 

OncePerRequestFilter의 경우  OPRF로 명명하겠다.

 

OPRF의 경우 모든 요청에 대해 한번만 실행하도록 보장된 필터이다.
→ 필터체인에서 딱한번만 실행되도록 보장된 필터라는 뜻

 

 

OPRF는 모든 요청에 공통적인 로직을 처리할 때에 유용하다고 한다.

ex) Spring Security와 JWT를 이용해 로그인을 구현 했다는 가정일 경우

모든 요청에서 JWT토큰을 검사해 유효성을 체크할 수 있음

 

 

 

 

 

차이점

 

AAPF와 OPRF는 용도가 다른 filter이기 때문에 차이점이라고 하기엔 모호하지만 

나는 이해하기 쉽게 차이점이라고 정리한다.

 

  • AAPF 인증을 처리하는데 사용하는 필터이고
  • OPRF 모든요청에 사용되는 필터이다

용도와 시점에 대해 정리해보면 각각의 어떤 용도로 사용되는 필터인지 좀 더 명확하게 이해할 수있다.

 

 

- 용도

AAPF    사용자의 인증처리하는데에 사용하며, 주로 로그인과 관련된 작업에 적합하다

OPRF  모든요청에 대해 공통적으로 수행되어야하는 작업에 적합

 

 

 

- 시점

AAPF 인증과정에서 특정한 시점에서 동작

OPRF 모든요청에서 수행되며 특정시점에 대한 제한은 없다.

 

 

 

 

결론

 

 

AAPF 로그인을 위한 로직에 관련된 기능을 수행하는 필터이고

OPRF 모든 요청에 대해 한번만 수행되는 필터이다

 

 

예시를 들면

AAPF  → 로그인을 수행할때 사용되는 필터

OPRF → 모든요청에서 토큰의 유효성을 체크하고 토큰의 유효성을 검사해 갱신하는 방식에 사용하는 필터

 

 

Spring Security의 경우 위의 AAPF와 OPRF의 필터를 기본적으로 사용한다고 하니 특별한 경우가 아닌 경우 두가지의 필터를 사용하면 될것같다.
특별한 경우는 나중에 찾아서 정리하는걸로....

 

 

나중에 Spring Security와 JWT를 이용한 코드를 작성하면서 해당 내용에 관련된 포스트를 올릴때 

해당 포스틑 언급하면서 나중에 봐도 알기 쉽게 사용할 수 있도록 정리하겠다.

 

 

[Spring Security] 스프링시큐리티 설정값들의 역할과 설정방법(2)

스프링시큐리티의 여러가지 설정값들의 역할과 설정방법을 상세히 알아봅니다. Spring Security 커스텀 필터를 이용한 인증 구현 - 스프링시큐리티 설정(2) 본 포스팅은 스프링시큐리티의 전반적인

kimchanjung.github.io

 

JWT는 편의성과 보안을위해 2가지의 토큰을 가진다.

  • Access Token
  • Refresh Token

위의 내용에 대해 좀더 자세한 내용으로는

JWT 토큰은 유저의 신원 및 권한을 결정하는 정보를 가지고 있는 데이터 조각이다.
JWT 토큰의 인증방식은 비밀키(개인키 or 대칭키)로 암호화 되어 있기 때문에 클라이언트와 서버는 안전하게 통신한다.
BUT
탈취 당한경우 문제가 발생한다고 한다
JWT 토큰을 탈취한 사람은 마치 신뢰할 사람으로 인증을 통과할 수 있기때문
심지어 본주인과 탈취한 사람인지에 대한 것을 서버는 구분할 수 없기 때문에 유효기간을 두는것이다.

유효기간이 짧은 경우 사용자가 로그인을 자주해야하므로 불편하고,
유효기간을 길게한 경우 탈취위험 노출이 크다. 
그래서 해결 방법인 토큰 2가지 (Access Token 과 Refresh Token)을 두는 것이라고 한다.

 

 

우선 핵심만 먼저 이야기하자면

 Access Token의 expiration(토큰만료시간)을  짧게 설정하고, Refresh Token의 expiration(토큰만료시간)을 길게 설정한다.

이렇게 하면 사용자의 편의성과 보안성이 증가한다.

 

 

 

토큰 관리방법

  • 로그인요청 후 정보를 비교하여 사용자로 확인된다면 Refresh Token을 발급하여 후 RefreshToken을 이용해 Access Token을 발급한다.
  • Access Token의 만료 시 Refresh Token을 비교후 일치 시 access token을 발급한다.
  • 클라이언트는 헤더(header)에 Access Toekn은 넣고 API 통신을 진행한다. (Authorization)
  • 서버의 경우 Refresh Token을 저장하고 있는다.
  • Refresh Token의 만료가 된경우 재로그인을 하도록 조치한다.

 

 

Access Token과 Refresh Token을 이용한 인증 절차 

1. Access Token 전송 시 만료 시간에 의한 실패의 경우 Refresh Token을 체크한다.

2. Refresh Token이 일치 한 경우 Access Token을 자동으로 발급하여 새로운 만료시간을 갖는다. (사용자는 로그아웃 X)

= Access Token가 탈취 된 경우 만료시간이 짧아 보안성이 좋음

= Refresh Token의 경우 위험

 

 

Refresh Token

저장위치 : 서버 즉 DB에 저장

→ Local Storage와 Cookie 보다 보안성이 좋음

토큰이 저장된 DB의 인뎃스 값을 Local Stoage나 Cookie에 저장

-> 인덱스 값을 hash 처리해서 보관 시 더욱 우수한 보안을 가질 수 있음. => DB는 Refrsh Token을 보관하는 곳을 HashMap, HashTable로 구현하게됨

 

 

'jwt' 카테고리의 다른 글

1. Jwt 개념정리  (0) 2024.01.06

1. JWT (Json Web Token)이란?


[JWT 개념]

JWT(JSON WEB TOKEN)이란 Json 포맷을 이용하여 사용자에 대한 속성으 저장하는 Claim 기반의 Web Token이다.

JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다.

주로 회원인증이나 정보전달 사용한다.

 

 

2. JWT 구조


[JWT 개념]

JWT의 구조는 3가지 부분으로 이루어지며 각각 Json 형태인 각부분은 Base64URl로 인코딩 되어 표현된다.

또한 각부분을 이어주기 위해 .(점)을 구분자로 사용한다.

  • Header (헤더)
  • Payload (페이로드)
  • Signature (서명)

JWT의 구조

 

1. Header

구조는 typ와 alg로 구성됨

  • typ : 토크의 타입지정 ex) JWT
  • alg : 알고리즘 방식을 지정하며, Signature(서명) 및 토큰 검증에 사용됨 ex) H256(SHA256) or RSA

 대표적으로 사용되는 알고리즘 (alg)은 아래의 리스트들이 있다

  • HMAC
  • SHA256
  • RSA
  • HS256 OR RS256
{
  "alg" : "HS256",
  "typ" : "JWT"
}

 

 

2.Payload

토큰에서 사용할 정보의 조각들인 Claim(클레임)이 담겨 있다. 
Claim은 name/value의 한 쌍으로 이루어져 있다.
{
  "sub": "1234567890", // 등록된 플레임
  "name": "John Doe", // 비공개 플레임
  "iat": 1516239022  // 등록된 플레임
}​

Claim은 3가지로 나누어 진다
  • 등록된 클레임 (Registered)
  • 공개 클레임 (Public)
  • 비공개 클레임 (Private)
1. 등록된 클레임 (Registered Claim) 
토큰의 정보를 표현 하기 위해 이미 정해진 종류의 데이터 (7종류가 있다)
선택적으로 작성가능 하며, key의 길이는 간결성을 위해 String이 3의 길이이다.
  • iss : 토큰 발급자 (issuer)
  • sub : 토큰의 제목 (subject) - unique한 값 사용, 사용자의 email 주로 사용
  • aud : 토큰의 대상자 (audience)
  • nbf : 토큰 활성날짜 (notbefore) - 이날이 지나기전 토크 활성화 되지 않음
  • exp: 토큰 만료시간 (expiration) - numericDate형식으로 되어 있어야함
  • iat : 토큰 발급시간 (issued at) - 토큰 발급 이후의 경과시간을 알 수 있음
  • jti : JWT 토큰 식별자 (JWT Id) -  중복 방지를 위해 사용, 일회용토큰(access Token)등에 사용됨

2. 공개 클레임 (Public Claim)
사용자 정의 클레임
공개용 정보를 위해 사용하며 충돌방지를 위해 Url 포맷을 이용
{
  "https:yongoh1253.tistory.com":true
}


3. 비공개 클레임 (Private Claim)
사용자 정의 클레임
서버와 클라이언트 사이에 임의로 지정한 정보를 저장

{
  "name": "John Doe"
}​

 

3. Signature (서명)

토큰을 인코딩하거나 유효성 검증을 할때 사용하는 고유화한 암호화 코드
Header와 Payload의 값을 각각 Base64Url로 인코딩하고 인코딩한 값을 다시 비밀키를 이용해 Header에서 정의한 알고리즘으로 해싱하고 이 값을 다시 Base64Url로 인코딩하여 생성
생성된 토큰은 Http 통신을 할때 'Authorization'이라는 key의 value로 사용
→ 일반적으로 value앞에 'Bearer '이 붙음
{
  "Authorization" : "Bearer {생성된 토큰 값}"
}

 

 

'jwt' 카테고리의 다른 글

jwt를 이용한 개발 시 이해한 내용 정리  (0) 2024.01.07

1. Spring Security란? 

스프링 시큐리티 (Spring Security)는 스프링 기반의 어플리케이션의 보안(인증과 권한, 인가)을 담당하는 스프링 하위 프레임워크.
보안과 관련해 체계적으로 많은 옵션들을 제공해주기 때문에 개발자의 입장에서는 하나하나 보안 관련 로직을 작성하지 않아도 된다는 장점이 있음.

 

 

1-1. Spring Security 관련 용어

  • 인증(Authentication) : 해당 사용자가 본인인지 확인하는 절차
  • 인가(Authorization) : 인증된 사용자가 요청한 자원에 접근 가능한지 결정하는 절차
  • 접근 주체(Principal) : 보호받는 Resource에 접근하는 대상
  • 비밀번호(Credential) : Resource에 접근하는 대상의 비밀번호
  • 권한 : 인증된 주체가 어플리케이션의 동작을 수행할 수 있도록 허락되어 있는지 결정
    • 인증 과정을 통해 주체가 증명된 이후 권한을 부여할 수 있다.
    • 권한 부여에 두 가지 영역이 존재하는데 웹 요청 권한과 메서드 호출 및 도메인 인스턴스에 대한 접근 권한 부여가 있다.



기본적으로
인증(Authentication)  → 인증성공 → 인가(Authorization)


Spring Security는 기본적으로 인증 절차를 거친 후에 인가 절차를 진행하게 되며, 인가 과정에서 해당 리소스에 대한 접근 권한이 있는지를 확인하게 됩니다. 이러한 인증과 인가를 위해 Principal을 아이디로, Credential을 비밀번호로 사용하는 인증 방식을 사용합니다.

 


기본적으로 인증 정보는 최종적으로 인메모리 세션 저장소인
SecurityContextHolder에 세션 - 쿠키 방식으로저장

 

 

 

 

2. Spring Security 동작원리

 

 

2-1 . Spring Security 동작원리 상세 (1~4)

동작원리의 1-4까지 흐름

1. 요청 (Request)
사용자가 로그인 정보를 요청한다.
예시) 로그인페이지에서 아이디와 비밀번호를 입력한다. 그럼 아이디와 비밀번호가 서버로 전송하게 된다.

AuthenticationFilter 는 사용자의 세션 ID(JSESSIONID)가 Security Context에 있는지 확인한다.
(여기서 Security Context란 아래의 모든 로직을 통과한 인증된 사용자의 정보(인증 개체)를 저장하는 공간이다.)
Security Context에 세션 ID가 없다면 아래 로직을 수행한다.

 


2. 토큰 생성

사용자가 보낸 아이디와 비밀번호를  AuthenticationFilter가 받아서 UsernamePasswordAuthenticationToken 토큰(인증용 객체)을 생성한다.

 AuthenticationFilter가 받고 아이디와 비번을 UsernamePasswordAuthenticationToken 토큰(인증용 객체)에 전달

 

 

3. 생성된 UsernamePasswordAuthenticationToken는 AuthenticationManager의 인증 메서드를 호출하는 데 사용된다.
여기서 AuthenticationManager는 단순한 인터페이스이며 실제 구현은 ProviderManager이다.

  • ProviderManager 에는 사용자 요청을 인증에 필요한 AuthenticationProvdier 목록이 있다.
  • ProviderManager는 제공된 각 AuthenticationProvdier를 살펴보고 전달된 인증 개체(UPAT)를 기반으로 사용자 인증을 시도한다.

※ UPAT  : UsernamePasswordAuthenticationToken는 너무길어서 여기부턴 UPAT로  명명하겠음

 


4. 토큰을 처리할 수 있는 AuthenticationProvider 선택
AuthenticationManager는 List 형태로 AuthenticationProvider들을 가지고 있는데, 실제로 인증을 할 AuthenticationProvider에게 인증용 객체를 다시 위임한다.
예시) AuthenticationManager는 인증을 담당하는 클래스이지만, 진짜는 AuthenticationManager가 가지고 있는 AuthenticationProvider 인터페이스들한테 "이거(인증용 객체) 줄테니 한번 인증처리가 가능한 AuthenticationProvider는 인증처리 해줘" 라고 또 떠넘기는 방식이다.

 

  • AuthenticationProvider의 리스트 중 일부
    • CasAuthenticationProvider
    • JaasAuthenticationProvider
    • DaoAuthenticationProvider
    • OpenIDAuthenticationProvider
    • RememberMeAuthenticationProvider
    • LdapAuthenticationProvider

 

 

2-2 . Spring Security 동작원리 상세 (5~7)

동작원리의 5~7까지 흐름

5. AuthenticationProvider는 사용자의 이름(username)을 기반으로 사용자의 세부정보를 검색하기위해 UserDetailsService를 사용할 수 있다.

 

 

5-1. AuthenticationProvider 인터페이스에서는 authticate() 메서드를 오버라이딩해 인증용객체를 파라미터로 받아 로그인페이지에서 입력한 사용자의 정보를 들고 올 수 있다. 

 

 

6, 7 . UserDetailsServiceDB에 저장된 회원의 비밀번호와 입력한 비밀번호가 일치하면 UserDetails인터페이스를 구현한 객체를 반환

UserDetailsService는 Spring Security의 인터페이스 이며 이를 구현한 서비스는 직접개발 해야한다.

즉, 아래 코드의 loadUserByUsername메소드를 오버라이딩해 DB와 비교하는 로직을 직접개발 해야한다.

public interface UserDetailService {
    UserDetail loadUserByUsername(String username) throws UsernameNotFoundException;
}

 

 

8. AuthenticationProvider 인터페이스에 의해 사용자가 성공적으로 인증되면, 완전히 채워진 인증개체가 반환된다.
인증에 실패하면 AuthenticaionException이 발생한다.
AuthenticaionException이 발생하면 인증 메커니즘을 지원하는 AuthenticationEntryPoint에 의해 처리된다.

사용자의 정보가 존재하지 않는경우 예외를 던진다고한다. (아래 코드 참고)

 

 

9. 인증완료

AuthenticationManager는 획득한 완전히 채워진 인증개체를 관련 인증 필터(AuthenticationFilter)로 다시 반환한다

 

 

10. SecurityContext에서 인증 개체 설정

AuthenticationFilter는 향후 필터 사용을 위해 획득한 인증 개체를 SecurityContext에 저장한다.

SecurityContext는 1번 로직에서 설명 했었다. 이 SecurityContext에 인증개체가 있는지를 확인하고, 

인증 로직이 수행되거나 수행되지 않는다.

SecurityContextHolder.getContext().setAuthentication(authentication);

 

 

 

각 Filter들의 역할

  • AuthenticationFilter
  • AuthenticationProvider
  • UserDetailsService
  • UserDetails

 

AuthenticationFilter

인증되지 않은 사용자와 인증된 사용자의 요청을 감시하고, AuthenticationManager에게 인증처리를 맡김
인증이 성공한다면 인증용 객체를 AuthenticationContext 객체에 저장하고 AuthenticationSuccessHandler 실행
실패 시 AuthenticationFailureHandler 실행

 

AuthenticationProvider

로그인페이지에서 입력한 정보와 DB에 저장된 정보를 비교
일치하다면 Authentication객체로 담아 AuthenticationManager에게 전달
만약 DB에 저장된 정보들 중 로그인페이지에서 입력한 정보와 일치하는 정보가 없다면 UsernameNotFoundException예외 처리

 

UserDetailsService

DB에서 유저정보를 가져오는 역할담당

 

UserDetails

사용자의 정보를 담은 인터페이스이며 직접 상속받아 사용한다.
유저객체에서 UserDetails를 상속받게 되면 구현해야할 메서드들이 있으며, 각 메서드들의 정의는 다음과 같다.

 

 

 

 

 

 

 

 

※ 참고 게시글 리스트 

 

 

[Spring Security] Spring Security의 개념과 동작 과정

📢 들어가기 전에 이번 포스팅에선 Spring Security가 무엇인지, 그리고 어떻게 동작하는 지에대해 알아본다. 인증, 인가, 보안 주체 Spring Security를 공부하기에 앞서 보안 용어에 대해 숙지해야한다.

doozi0316.tistory.com

 

 

Spring Security 동작 원리

Spring Security란 ? 스프링에서 제공하는 보안 관련 프레임워크다. 사용자의 요청에 대한 인증, 사용자가 권한이 있는지 확인하는 인가, 응답 등등 보안에 관련해서 많은 부분을 제공해주고 있기 때

skatpdnjs.tistory.com

 

spring_seurity의 설정 후 oauth2.0으로 kakao 로그인 기능으 구현했다.

 

 

그런데 카카오의 로그인 까지는 정상적으로 동작이 되지만 자꾸 리다이렉션이 발생한다는 내용이 브라우저에 표시되었다.

 

확인해 보니 spring security에서 사용하는 yml설정 중에 redirect-uri는 기본양식이 있다고 한다.

 

 

Spring Security + OAuth2.0 + JWT

✔︎ Spring Security + OAuth 2.0 Redirect URI Authorization server(Google, Kakao 등)에서 사용자 인증 후 리다이렉션할 URI이다. 쉽게 말해 타사 서비스에서 우리 서비스로 돌아올 수 있는 경로라고 생각하면 된다.

velog.io

아래의 양식으로 변경 해주니 정상적으로 동작했다.

 

 

기존

 - >

redirect-uri: http://localhost:8080/oauth2/login/kakao

 

수정후 

->

redirect-uri: http://localhost:8080/login/oauth2/code/kakao

Spring Security 의 사용방법 및 메소드 설명이 정리되어있는 블로그를 남겨둔다.

 

Spring Security 간단한 사용방법

📌 Intro 항해99 주특기 숙련주차에서 처음 Spring Security를 접하고 미니프로젝트 주차에서도 Spring Security를 접했다. 물론 숙련주차에서 작성한 코드를 기반으로 했지만 Spring Security는 너무 어렵다..

comclothing.tistory.com

 

사용 방법의 간단한 예제를 설명해주는 포스트가 있어 참고하기위해 남겨둔다.

 

Security 버전의 경우 5.7을 기준으로 작성된것으로 보이나 참고하면 도움이 될 것 같아 링크를 남겨둔다.

 

 

Spring Security 간단한 사용법

Spring Security 간단한 사용법

velog.io

 

+ Recent posts