인증과 인가에 대해서 간단하게 다루고  Spring Security에서의 인증과 인가 흐름에 대해서도 다루는 글이다. 

 

인증

인증이란 사용자가 누구인지 확인하는 과정이다. 

  • 아이디/비밀번호 기반 인증 
  • OAuth2.0/JWT기반 인증 
  • 소셜 로그인(Google, Facebook 등)
  • API Key / Token 기반 인증

 

인가 

인가란  요청하는 유저가 권한이 있는지 체크하는 절차이다.

  • jwt에 유저의 권한 정보도 전달해서 수월하게 인가 체크 

 

 

 

인증(Authentication)과 인가(Authorization)의 차이

보안에 관련된 작업을 위한 절차라는 공통점이 있지만 역할에서 다르다.

인증은 인가로 이어지지만 인가는 인증으로 이어지지 않는 차이가 있다. 

 

 

 

 

 

Spring Security란?

Spring Security는 스프링 기반 애플리케이션의 보안을 책임지는 프레임워크로, 주로 인증(Authentication)과 인가(Authorization) 기능을 제공합니다. 이 프레임워크를 통해 애플리케이션에서 접근 제어를 설정하고 관리할 수 있습니다.

 

Spring Security의 가장 큰 장점은 복잡한 보안 로직을 직접 구현할 필요 없이, 이미 검증된 보안 메커니즘을 제공한다는 것입니다. 로그인, 권한 부여, 암호화, 세션 관리 등을 간단한 설정만으로 쉽게 구현할 수 있어 개발 시간과 노력을 절약할 수 있습니다.

 

 

Spring Security의 주요 기능

  1. 인증 처리: Spring Security는 폼 기반 로그인, OAuth2 소셜 로그인, Basic Authentication 등 다양한 인증 방식을 지원합니다.
  2. 인가 처리: 인증된 사용자가 접근할 수 있는 리소스를 정의하고 관리할 수 있으며, 역할 기반으로 접근을 제어할 수 있습니다.
  3. 보안 설정: URL 경로에 따라 접근 권한을 설정할 수 있으며, 특정 리소스에 대해 로그인한 사용자만 접근 가능하게 할 수 있습니다.
  4. 암호화: 사용자 비밀번호는 안전하게 암호화되어 저장되며, Spring Security는 다양한 암호화 알고리즘을 지원하여 데이터 유출을 최소화합니다.
  5. 세션 관리: Spring Security는 세션 고정 공격(session fixation)을 방지하는 등 세션 관리를 위한 다양한 기능을 제공합니다.

 

Spring Security : 필터 기반 구조

필터는 웹 애플리케이션에서 문지기 역할을 하는 도구입니다. 웹 사이트에 들어오는 모든 요청(예: 사용자가 웹 페이지를 열 때의 요청)과 나가는 모든 응답(예: 서버가 웹 페이지 내용을 사용자에게 보낼 때)을 통과하는 곳이 필터입니다.

Spring Security는 여러 개의 보안 필터를 통해 인증, 권한 부여, 공격 방지 등의 작업을 처리합니다. 각 필터는 요청이 들어올 때 또는 응답을 보낼 때 특정 보안 작업을 수행합니다. 이 필터들은 필터 체인(Filter Chain)이라는 구조로 연결되어 있으며, 특정 순서대로 실행됩니다.

 

 

Spring Security 인증 흐름

1. 클라이언트가 HTTP요청을 보냄

  •  사용자가 로그인 요청을 하면 요청이 AuthenticationFilter로 전달됨.

2. AuthenticationFilter가 인증 객체 생성

  • 사용자의 ID와 비밀번호를 포함한 UsernamePasswordAuthenticationToken을 생성.

3. AuthenticationManager에게 인증 요청을 전달 

  • AuthenticationFilter는 AuthenticationManager를 호출하여 인증을 시도.

4. AuthenticationManager가 AuthenticationProvider에게 인증 요청을 위임

  • AuthenticationManager는 하나 이상의 AuthenticationProvider에게 인증을 수행하도록 위임.

5. UserDetailsService에서 사용자 정보를 조회

  • AuthenticationProvider는 UserDetailsService를 이용하여 사용자의 정보를 검색.

6. UserDetailsService가 UserDetails 객체를 반환 

  • UserDetailsService는 데이터베이스 또는 기타 저장소에서 사용자를 찾고, UserDetails 객체를 반환.

7. AutenticationProvider가 사용자 정보 검증 

  • UserDetails 객체를 이용해 사용자의 비밀번호를 검증.

8. 인증이 성공하면 Authentication 객체를 생성 

  • 인증이 성공하면 Authentication 객체를 생성하여 반환.

9.  AuthenticationFilter가 SecurityContextHolder에 인증 정보 저장 

  • SecurityContextHolder는 인증된 Authentication 객체를 저장.

10. 인증 완료 후 요청을 계속 진행 

  • 인증이 성공하면 사용자는 보호된 리소스에 접근할 수 있음.

 

 

 

Spring Security 기반 인가(Authorization) 흐름

https://velog.io/@penrose_15/Spring-Security%EC%9D%98-%EC%9D%B8%EA%B0%80-%EC%B2%98%EB%A6%AC-%ED%9D%90%EB%A6%84

 

1. 요청(Request)

  • 사용자가 특정 리소스(API, 페이지 등)에 접근하려고 요청을 보냄.
  • 예: 또는 세션 기반 인증일 경우: 
  • GET /admin/dashboard Cookie: JSESSIONID=xyz123
  • jwt토큰기반
    GET /admin/dashboard Authorization: Bearer <JWT_TOKEN>
     

2. SecurityFilterChain을 통한 요청 가로채기

  • Spring Security의 필터 체인(SecurityFilterChain)이 요청을 가로챔.
  • 인증되지 않은 사용자인 경우, AuthenticationEntryPoint를 통해 401 응답.

3. JwtAuthenticationFilter (JWT 사용 시)

  • 요청 헤더에서 JWT를 가져와 검증 수행.
  • 검증이 성공하면 Authentication 객체를 SecurityContextHolder에 저장.
  • 세션 기반 인증일 경우, 자동으로 SecurityContext에서 사용자를 확인.

4. FilterSecurityInterceptor를 통한 접근 권한 확인

  • FilterSecurityInterceptor가 요청된 URL에 대한 권한 체크를 수행.
  • Spring Security의 설정(http.authorizeRequests())을 기반으로 접근 가능 여부를 결정. 
    • 사용자의 Authentication 객체에서 역할(Role)을 가져와 인가 여부 확인.
  • java
    복사편집
    http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") // 관리자만 접근 가능 .antMatchers("/user/**").hasAnyRole("USER", "ADMIN") // 일반 사용자, 관리자 가능 .anyRequest().authenticated(); // 그 외 모든 요청은 인증 필요
  • 예를 들어, 다음과 같은 설정이 되어 있다고 가정하면:

5. 접근 승인 또는 거부

  • 승인(Authorized): 사용자의 역할이 요구된 권한과 일치하면, 컨트롤러로 요청을 전달.
  • 거부(Forbidden, 403 에러): 사용자가 필요한 권한이 없으면 AccessDeniedHandler를 통해 403 응답.

 

 

 

Stateful(상태유지) vs Stateless 인증방식  (상태없음)

Stateful이란 유저(클라이언트)의 정보가 서버측에 저장되어 있음을 나타냄.

Stateless이란 유저(클라이언트)의 정보가 클라이언트 측에 저장되어 있음을 나타낸다.

 

서버에 유저의 상태가 저장되어 있지 않다면 서버에 요청을 보낼 때마다 유저의 상태를 반복적으로 전달해야 하므로 성능에도 안 좋고 복잡할 것이라는 생각이 들 수도 있지만

갑자기 클라이언트의 요청이 급증했다고 생각해서 서버를 늘리고 첫번째 요청과 두번째 요청을 처리하는 서버가 다르다고 가정해보자.

그럴경우 매번 필요한 데이터를 전달하는 statleless방식이 효율적일 것이다. 상태를 저장하지 않는 쪽에서 훨씬 수월하게 요청을 처리할 수 있을 것이다. 

 

 

방식 Stateless 인증  Stateful 인증
개념 서버가 사용자 상태(Session)를 유지하지 않음 서버가 세션(Session)에 인증 정보를 저장
사용 방식 JWT, OAuth 2.0 세션(Session), 쿠키(Cookie)
인증 정보 저장 위치 클라이언트(토큰 저장) 서버 (Session 저장소)
스케일링 확장성 뛰어남 (서버가 인증 상태 저장 안 함) 확장성이 낮음 (세션 공유 필요)
예제 REST API, 마이크로서비스 전통적인 웹 애플리케이션 (JSP, Thymeleaf)

 

JWT(JSON WEB TOKEN)을 사용하면 암호화된 토큰을 클라이언트에 전달하고 이 토큰을 클라이언트에서 바꿀 수 없게 함으로써 효율적으로 stateless를 적용할 수 있다. (단 탈취 위험 존재) 

 

session방식은 서버에 클라이언트의 정보를 저장하고 클라이언트에게 세션 ID를 전달해서 이를 가지고 식별하는 방식이다.

 

시큐리티는 두 방식 모두 구현이 가능하다. 

 

Stateless (JWT) 방식을 선택해야 하는 경우

  • REST API, 마이크로서비스 환경
  • 서버 확장이 필요한 경우 (Load Balancing)
  • OAuth 2.0 / OpenID Connect 기반 인증 사용
  • 클라이언트가 다양한 환경(웹, 모바일, API)에서 접근

Stateful (Session) 방식을 선택해야 하는 경우

  • 단일 서버 또는 작은 규모의 웹 애플리케이션
  • 보안이 중요한 기업 내부 시스템 (권한 변경 즉시 반영 필요)
  • 브라우저 기반 웹 애플리케이션 (CSRF 보호 가능)

 

 

OAuth2.0 + JWT 인증 

OAuth 2.0 개념

https://hudi.blog/oauth-2.0/

OAuth 2.0은 사용자가 직접 비밀번호를 입력하지 않고도 외부 서비스(예 Google, Facebook, Naver)를 통해 애플리케이션에 안전하게 로그인할 수 있도록 도와주는 권한 부여 프로토콜입니다.

OAuth 2.0 주요 개념

  • Resource Owner (사용자) → 자신의 리소스(예: 계정 정보)를 보호하고 관리하는 사람
  • Client (클라이언트) → 리소스에 접근하려는 애플리케이션 (예: 모바일 앱, 웹 앱)
  • Authorization Server (인가 서버) → 클라이언트에게 Access Token을 발급
  • Resource Server (리소스 서버) → 실제 데이터를 저장하고 보호하는 서버 (예: API 서버)

OAuth 2.0 인증 흐름

  1. 사용자가 클라이언트 애플리케이션에 로그인 요청
  2. 클라이언트가 Authorization Server로 인증 요청
  3. Authorization Server가 사용자 인증 후 Access Token 발급
  4. 클라이언트가 Resource Server로 요청 시 Access Token을 포함
  5. Resource Server가 Access Token을 검증 후 데이터 제공

2. JWT(JSON Web Token) 개념

JWT 구조 예시 (출처: BizSpring)

JWT는 서버와 클라이언트 간의 인증을 위한 JSON 기반의 토큰입니다.
JWT는 Stateless(무상태) 인증에 적합하여 OAuth 2.0과 함께 사용됩니다.

JWT 구조

JWT는 세 부분으로 구성됩니다. Header.Payload.Signature

예제:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwicm9sZSI6IkFETUlOIiwiZXhwIjoxNjcwMDAwMDAwfQ.7d7f8...
 
  1. Header → 토큰 타입과 암호화 알고리즘 (예: HS256, RS256)
  2. Payload → 사용자 정보(클레임), 역할(Role), 만료 시간 등
  3. Signature → 토큰 위조 방지를 위한 서명

JWT 예제 (Payload)

 
{ "sub": "user123", "role": "ADMIN", "exp": 1718202000 }
  • sub: 사용자 ID
  • role: 사용자의 역할 (예: ADMIN, USER)
  • exp: 토큰 만료 시간

JWT는 인가(Authorization) 정보도 포함할 수 있어 별도의 세션을 유지할 필요가 없음.


3. OAuth 2.0과 JWT를 활용한 보안 시스템

OAuth 2.0과 JWT를 결합하면 보안성과 확장성을 모두 갖춘 인증 시스템을 만들 수 있습니다.

OAuth 2.0 + JWT 인증 흐름

Access Token을 JWT로 발급하여, 서버가 인증 상태를 저장할 필요 없음
JWT를 포함한 요청을 처리하는 Resource Server는 토큰을 검증하여 사용자 인가
Refresh Token을 활용하여 Access Token을 갱신 가능

1. 사용자 로그인 요청

  • 사용자가 Client (예: 웹, 모바일 앱)에 로그인 요청
  • 클라이언트는 Authorization Server로 사용자 인증 요청

2. Authorization Server에서 JWT 발급

  • 사용자가 인증되면 Access Token(JWT)Refresh Token 발급
  • Access Token은 짧은 유효기간(예: 1시간)
  • Refresh Token은 더 긴 유효기간(예: 30일)

3. 클라이언트가 Access Token 포함하여 API 요청

  • 클라이언트는 Authorization: Bearer <JWT> 헤더를 포함하여 요청
  • Resource Server는 JWT 검증 후 사용자 정보 확인 및 데이터 반환

4. Access Token 만료 시 Refresh Token 사용

  • Access Token이 만료되면 클라이언트는 Refresh Token을 사용하여 새 Access Token 요청
  • Authorization Server가 Refresh Token을 검증 후 새로운 Access Token 발급

 

 

정리

인증과 인가에 대해서 간략하게 정리하고 Spring Seucirty에서 인증과 인가 과정에 대해서도 다뤘다!

 

참고 사이트 

https://blu-blu.tistory.com/97#%E2%9C%85%20Spring%20Security%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC%ED%95%98%EB%8A%94%20%EC%9D%B4%EC%9C%A0-1

+ Recent posts