Spring Boot Security 가이드 1편
Updated:
Spring Boot Security Role Based Flow
Tips
Spring Security 적용시 필수 구현:
- Spring Security Dependency
- Spring Security Config
- UserDetailsService 상속
- loadUserByUsername
- CSRF Token Header
Spring Boot Security 구현
Dependency & Config
1. pom.xml에 Dependency 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency> <!-- thymeleaf사용할 경우 추가 -->
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
2. Security Config
package com.skcc.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.skcc.demo.context.auth.domain.authority.AuthorityService;
import lombok.AllArgsConstructor;
@Configuration
@EnableWebSecurity
@AllArgsConstructor
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private AuthorityService authorityService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) throws Exception {
// static 디렉터리의 하위 파일 목록은 인증 무시 ( = 항상통과 )
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**", "/lib/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 페이지 권한 설정
.antMatchers("/", "/login", "/error**", "/signup").permitAll()
.antMatchers("/manage/**").hasAnyRole("MANAGER")
.antMatchers("/counselor/**").hasAnyRole("COUNSELOR")
.antMatchers("/partner/**").hasRole("PARTNER_COMPANY")
.antMatchers("/members/**").hasRole("MEMBER_COMPANY")
.antMatchers("/admin/**").hasRole("SYS_ADMIN")
.antMatchers("/usermanage/**").hasRole("SYS_ADMIN")
.antMatchers("/**").permitAll().and() // 로그인 설정
.formLogin().loginPage("/login")
.defaultSuccessUrl("/login/result").permitAll()
.failureUrl("/login?error")
.and() // 로그아웃 // 설정
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/user/logout"))
.clearAuthentication(true)
.logoutSuccessUrl("/logout/result")
.invalidateHttpSession(true).and()
// 403 예외처리 핸들링
.exceptionHandling().accessDeniedPage("/login/denied");
}
@Override
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(authorityService).passwordEncoder(passwordEncoder());
}
}
3. Security Config 상세 설명
1. @EnableWebSecurity
- @Configuration 클래스에 @EnableWebSecurity 어노테이션을 추가하여 Spring Security 설정할 클래스라고 정의
- 설정은 WebSebSecurityConfigurerAdapter 클래스를 상속받아 메서드를 구현하는 것이 일반적인 방법
- Web 보안 활성화
2. WebSecurityConfigurerAdapter 클래스
- WebSecurityConfigurer 인스턴스를 편리하게 생성하기 위한 클래스
3. passwordEncoder()
- BCryptPasswordEncoder: Spring Security에서 제공하는 비밀번호 암호화 객체
- Service에서 비밀번호를 암호화할 수 있도록 Bean으로 등록
4. configure() 메소드를 overriding 해 Security 설정
- configure(WebSecurity web)
- WebSecurity는 FilterChainProxy를 생성하는 필터
- web.ignoring().antMatchers(“/css/”, “/js/”, “/img/”, “/lib/”);
- 해당 경로의 파일들은 Spring Security가 무시할 수 있도록 설정
- 즉, 이 파일들은 무조건 통과
- configure(HttpSecurity http)
- HttpSecurity를 통해 HTTP 요청에 대한 웹 기반 보안을 구성.
- authorizeRequests()
- HttpServletRequest에 따라 접근(access)제한
- antMatchers() 메서드로 특정 경로를 지정하며, permitAll(), hasRole() 메서드로 역할(Role)에 따른 접근 설정.
*Role은 권한을 의미. 즉 어떤 페이지는 관리지만 접근해야 하고, 어떤 페이지는 회원만 접근해야할 때 그 권한을 부여하기 위해 역할을 설정하는 것.
→ 예를 들어,- .antMatchers(“/admin/**”).hasRole(“SYS_ADMIN”)
- /admin 으로 시작하는 경로는 SYS_ADMIN 롤을 가진 사용자만 접근 가능.
- .antMatchers(“/**”).permitAll()
- 모든 경로에 대해서는 권한없이 접근 가능합니다.
- .anyRequest().authenticated()
- 모든 요청에 대해, 인증된 사용자만 접근하도록 설정할 수도 있음
- .anonymous()
- 인증되지 않은 사용자가 접근할 수 있음.(예제 적용 안함)
- .antMatchers(“/admin/**”).hasRole(“SYS_ADMIN”)
- formlogin()
- form 기반으로 인증. 로그인 정보는 기본적으로 HttpSession을 이용.
- /login 경로로 접근하면, Spring Security에서 제공하는 로그인 form을 사용할 수 있음. (예제에 적용됨)
- .loginPage(“/login”)
- 기본 제공되는 form 말고, 커스텀 로그인 폼을 사용하고 싶으면 loginPage() 메서드를 사용.
- 이 때 커스텀 로그인 form의 action 경로와 loginPage()의 파라미터 경로가 일치해야 인증을 처리할 수 있음. ( login.html에서 확인 )
- .usernameParameter(“파라미터명”)
- 로그인 form에서 아이디는 name=username인 input을 기본으로 인식하는데, usernameParameter() 메서드를 통해 파라미터명을 변경할 수 있음.
→ 단, login.html의 id 입력 부분의 name 값과 일치 시켜줘야함 (예제엔 적용x)
- 로그인 form에서 아이디는 name=username인 input을 기본으로 인식하는데, usernameParameter() 메서드를 통해 파라미터명을 변경할 수 있음.
- .defaultSuccessUrl(“/login/result”)
- 로그인이 성공했을 때 이동되는 페이지이며, 마찬가지로 컨트롤러에서 URL 매핑이 되어 있어야함.
- logout()
- 로그아웃을 지원하는 메서드이며, WebSecurityConfigurerAdapter를 사용할 때 자동으로 적용.
- 기본적으로 “/logout”에 접근하면 HTTP 세션을 제거.
- .logoutRequestMatcher(new AntPathRequestMatcher(“/user/logout”))
- 로그아웃의 기본 URL(/logout) 이 아닌 다른 URL로 재정의.
- .invalidateHttpSession(true)
- HTTP 세션을 초기화하는 작업.
- deleteCookies(“KEY명”)
- 로그아웃 시, 특정 쿠기를 제거하고 싶을 때 사용하는 메서드 ( 예제에는 적용안함 )
- .exceptionHandling().accessDeniedPage(“/user/denied”);
- 예외가 발생했을 때 exceptionHandling() 메서드로 핸들링할 수 있음.
- 예제에서는 접근권한이 없을 때, 로그인 페이지로 이동하도록 명시
- configure(AuthenticationManagerBuilder auth)
- Spring Security에서 모든 인증은 AuthenticationManager를 통해 이루어지며 AuthenticationManager를 생성하기 위해서는 AuthenticationManagerBuilder를 사용.
- 로그인 처리 즉, 인증을 위해서는 UserDetailService를 통해서 필요한 정보들을 가져오는데, 예제에서는 서비스 클래스(authorityService)에서 이를 처리.
- 서비스 클래스에서는 UserDetailsService 인터페이스를 implements하여, loadUserByUsername() 메서드를 구현해야함. → 구현 상세의 UserDetailService 참조
- 비밀번호 암호화를 위해, passwordEncoder를 사용
- Spring Security에서 모든 인증은 AuthenticationManager를 통해 이루어지며 AuthenticationManager를 생성하기 위해서는 AuthenticationManagerBuilder를 사용.
프로젝트 예제 Github 주소 :
https://github.com/Juyounglee95/auth-sample.git
구현 참고 자료:
1. Spring Boot Security 활용 Login, Sign up 기본 예제
2. Spring Boot Security 활용 User Custom, Role Custom 예제
3. Spring Boot Security CSRF 예제 - 13.4.3 Include the CSRF Token 참고