[SPRING] 스프링시큐리티(Spring Security)를 사용해보장
Maven Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Gradle Dependency
implementation 'org.springframework.boot:spring-boot-starter-security'
어노테이션
@Configuration
설정 컴포넌트라고 선언한다.
@EnableWebSecurity
스프링 시큐리티 지원을 가능하게 한다. 이걸 설정 객체에 붙혀주면 SpringSecurityFilterChain에 등록된다.
@AuthenticationPrincipal
매개변수에 선언한다. 이게 붙은 매개변수는 SecurityContextHolder에 저장된 인증 객체(Authentication 객체)의 principal 부분(userDetails)을 가져온다.
@Secured("ROLE_ADMIN")
내가 허가할 권한을 넣어준다.
@EnableGlobalMethodSecurity(securedEnabled = true)
Secured 어노테이션을 사용할 수 있게 해주려면 WebSecurityConfig쪽에 이 어노테이션을 선언해줘야 한다.
객체
WebSecurityConfigurerAdapter
- Security Dependency를 추가한 이후 기본적인 security를 설정및 구현하는 클래스
- HttpSecurity 라는 세부적인 보안기능을 설정할수 있는 API를 제공하는 클래스를 생성한다.
SecurityFilterChain
- Filter 보다 먼저 실행된다. 여러개의 SecurityFilterChain을 @Order를 통해 여러개를 만들어 순서를 정할 수 있다.
HttpSecurity
- csrf().disable() : 사이트간 요청 위조. csrf가 설정되어있으면 html에서 CSRF 토큰값을 넘겨주어야 요청 수신이 가능하다. 쿠키를 사용하기 때문에 html 관련이라서 REST API에서는 disable이 가능하다.
SecurityContextHolder
스프링 시큐리티로 인증을 한 사용자의 상세 정보를 저장한다.
SecurityContext 란? SecurityContextHolder 로 접근할 수 있으며 Authentication 객체를 가지고 있다.
PasswordEncoder
암호화된 비밀번호이다. 암호화 종류가 많은데 BCryptPasswordEncoder를 사용하자.
제공 API
인증 API | 인가 API |
http.formLogin() | http.authorizeRequests().antMatchers(/admin) |
http.logout() | http.authorizeRequests().hasRole(USER) |
http.csrf() | http.authorizeRequests().permitAll() |
http.httpBasic() | http.authorizeRequests().authenticated() |
http.authorizeRequests().fullyAuthentication() | |
http.RememberMe() | http.authorizeRequests().access(hasRole(USER)) |
http.ExceptionHandling() | http.authorizeRequests().denyAll() |
http.addFilter() |
antMatchers 속성
permitAll : 전부 허가한다
authenticated : 인증을 한다.
anonymous : 익명의 사용자만 허용한다.
hasAnyRole : 권한을 가진 사용자만 요청을 받아들인다.
등등...
Security Config 설정
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // 요청에 의한 보안검사 시작
.antMatchers("/images/**").permitAll() // image 폴더를 login 없이 허용
.antMatchers("/css/**").permitAll() // css 폴더를 login 없이 허용
.anyRequest().authenticated() // 어떤 요청이든 보안검사를 한다.
.and()
// 로그인 세팅 코드
.formLogin() // 보안 검증은 formLogin방식으로 하겠다.
.loginPage("/user/login") //사용자 정의 로그인 페이지
.defaultSuccessUrl("/") //로그인 성공 후 이동 페이지
.failureUrl("/user/login?error") // 로그인 실패 후 이동 페이지
.usernameParameter("username")//아이디 파라미터명 설정
.passwordParameter("password")//패스워드 파라미터명 설정
.loginProcessingUrl("/login")//로그인 Url을 변경 가능
.successHandler(loginSuccessHandler())//로그인 성공 후 핸들러 (해당 핸들러를 생성하여 핸들링 해준다.)
.failureHandler(loginFailureHandler());//로그인 실패 후 핸들러 (해당 핸들러를 생성하여 핸들링 해준다.)
.permitAll() //사용자 정의 로그인 페이지 접근 권한 승인
.and()
// 로그아웃 세팅 코드
.logout() //로그아웃 처리
.logoutUrl("/logout")// 로그아웃 처리 URL
.logoutSuccessUrl("/login")//로그아웃 성공 후 이동페이지
.deleteCookies("JSESSIONID","remember-me")//로그아웃 후 쿠키 삭제
.addLogoutHandler(new LogoutHandler() {
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
HttpSession session = request.getSession();
session.invalidate();
}
})//로그아웃 핸들러
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect("/login");
}
})//로그아웃 성공 후 핸들러
.deleteCookies("remember-me");//쿠키 삭제
.permitAll();
}
}
모르는 용어
WebSecurityCustomizer
requestMatchers
PathRequest
atCommonLocations
HttpSecurity
exceptionHandling : 에러가 날때 핸들링
- accessDeninedPage : 403 에러 처리. 인증과는 별개로 추가적인 권한이 충족하지 않은 경우
- authenticationEntryPoint : 401 에러 처리. Authorization 즉, 인증과정에서 실패할 경우
addFilterBefore