Spring Security
Spring 기반의 어플리케이션 인증, 권한, 인가 등의 보안을 담당하는 스프링 하위 프레임워크
스프링 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공
'인증'과 '권한'에 대한 부분을 Filter 흐름에 따라 처리
보안과 관련해 체계적으로 많은 옵션을 제공해주기 때문에 개발자 입장에서 일일이 보완관련 로직을 작성하지 않아도 되는 장점이 존재
Hello Spring Security :: Spring Security
You can now run the Spring Boot application by using the Maven Plugin’s run goal. The following example shows how to do so (and the beginning of the output from doing so): Running Spring Boot Application $ ./mvn spring-boot:run ... INFO 23689 --- [ resta
docs.spring.io
Spring Security 적용 방법
스프링 시큐리티 프레임워크 추가
build.gradle에 다음 코드 붙여넣기
// 스프링 시큐리티
implementation 'org.springframework.boot:spring-boot-starter-security'
스프링 시큐리티 활성화
1. WebSecurityConfig 클래스 생성
2. 어노테이션 추가
- @Configuration
- @EnableWebSecurity
3. SecurityFilterChain을 Bean으로 등록하고 아래 코드와 같이 CSRF 등 설정
- CSRF(사이트 간 요청 위조, Cross-site request forgery)
- 공격자가 인증된 브라우저에 저장된 쿠키의 세션 정보를 활용하여 웹 서버에 사용자가 의도하지 않은 요청을 전달하는 것
- CSRF 설정이 되어있는 경우 html 에서 CSRF 토큰 값을 넘겨주어야 요청을 수신 가능
- 쿠키 기반의 취약점을 이용한 공격 이기 때문에 REST 방식의 API에서는 disable 가능
- POST 요청마다 처리해 주는 대신 CSRF protection 을 disable
// WebSecurityConfig (springboot 2.7 이상)
package com.xxx.springsecurity.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration // 2. Configuration, 아래 EnableWebSecurity 어노테이션 추가
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig { // 1. WebSecurityConfig 클래스 생성
@Bean // SecurityFilterChain을 Bean으로 등록
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated();
// 로그인 사용
http.formLogin();
return http.build();
}
}
Spring Security 주요 컴포넌트
Spring Security와 Filter
- Spring Security는 요청이 들어오면 Servlet FilterChain을 자동으로 구성한 후 거치게 한다
- FilterChain은 여러 Filter를 chain 형태로 묶어놓은 것을 의미
- Filter
- 톰캣과 같은 웹 컨테이너에서 관리되는 서블릿 기술
- Client 요청이 전달되기 전후의 URL 패턴에 맞는 모든 요청에 필터링을 해준다
- CSRF, XSS 등의 보안 검사를 통해 올바른 요청이 아닐 경우 이를 차단
- Spring Security는 이러한 기능을 활용하기 위해 Filter를 사용하여 인증과 인가를 구현
SecurityFilterChain
- Spring의 보안 Filter를 결정하는데 사용되는 필터
- session, jwt 등의 인증 방식들을 사용하는데 필요한 설정을 분리할 수 있는 환경을 제공

AbstractAuthenticationProcessingFilter
- 사용자의 credential을 인증하기 위한 베이스 Filter
- SecurityFilterChain 안에서 사용자 인증 처리를 하는 Filter라고 볼 수 있음

UsernamePasswordAuthenticationFilter
- AbstractAuthenticationProcessingFilter를 상속한 Filter
- Form Login 기반을 사용할 때 username과 password를 확인하여 인증
- Form Login 기반은 인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인페이지를 반환하는 형태


SecurityContextHolder
- Spring Security로 인증을 한 사용자의 상세 정보를 저장
- SecurityContext는 SecurityContextHolder로 접근할 수 있으며 Authentiaction 객체를 가지고 있다.

// 예시코드
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
Authentication
- 현재 인증된 사용자를 나타내며 SecurityContext에서 가져올 수 있다
- principal : 사용자를 식별 (Username / Password 방식으로 인증할 때 보통 UserDetails 인스턴스)
- credentials : 주로 비밀번호, 대부분 사용자 인증에 사용한 다음 비움
- authorities : 사용자에게 부여한 권한을 GrantedAuthority로 추상화하여 사용
<UserDetails>
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
UserRoleEnum role = user.getRole();
String authority = role.getAuthority();
System.out.println("authority = " + authority);
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(simpleGrantedAuthority);
return authorities;
}
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
// UsernamePasswordAuthenticationToken는
// Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로,
// 인증객체를 만드는데 사용된다.
UserDetailsService
- username/password 인증 방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환
- Custom하여 Bean으로 등록 후 사용이 가능
UserDetails
- 검증된 UserDetails는 UsernamePasswordAuthenticationToken 타입의 Authentication을 만들 때 사용되며 해당 인증객체는 SecurityContextHoler에 세팅
- Custom하여 사용 가능