pom.xml
<!-- 4. Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
securityConfig.java
package com.codesign.base.configure;
import com.codesign.base.jwt.JwtAuthenticationFilter;
import com.codesign.base.jwt.JwtAuthorizationFilter;
import com.codesign.base.service.UserService;
import lombok.RequiredArgsConstructor;
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // 위변조 방지 미사용
http.cors().configurationSource(corsFilter()) // cors설정
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session 미사용
.and().formLogin().disable() // formlogin 미사용
.httpBasic().disable() // Baerer 사용으로 Basic방식 미사용
// 다음 단계에서 설정 임시 주석처리
// .addFilter(new JwtAuthenticationFilter(authenticationManager()))
// .addFilter(new JwtAuthorizationFilter(authenticationManager(), userService))
.authorizeRequests()
.antMatchers("/api/v1/user/**").permitAll()
.antMatchers("/api/v1/manager/**").access("hasRole('ROLE_MANAGER')")
.anyRequest().permitAll();
}
@Bean
public CorsConfigurationSource corsFilter(){
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 자바스크립트 응답을 처리할 수 있게 할지 설정(ajax, axios)
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/*", config);
// TODO /api/* 으로 요청이 왔을때, Allowed 된 요청만 받는지 확인하기
return source;
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
configure(HttpSecurity http)
속성 | 설명 |
---|---|
csrf().disable() | 위변조 방지 미사용 >> 토큰 방식 사용 |
cors().configurationSource(corsFilter()) | corsFilter 설정 |
sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) / | session 미사용 >> 토큰 방식 사용 |
formLogin().disable() | 로그인 폼 미사용 >> UsernamePasswordAuthenticationFilter 미동작 따로 필터등록 필요함 formLogin()을 사용하게 되면 서버로 로그인 요청시, username과 password로 인증하는 로직(UserDetailsService)을 수행하고, 세션에 저장한다. >> 토큰 발급할 것이므로 비활성 |
httpBasic().disable() | httpBasic방식 미사용 >> Bearer방식 사용 |
authorizeRequests() | 권한설정 시작 |
antMatchers("/api/v1/user/**") | 해당 path에 관한 권한 설정 |
permitAll() | 모두 허용 |
access("hasRole('ROLE_MANAGER')") | MANAGER만 허용 |
csrf().disable()
CSRF의 취약점은 공격자가 사용자가 의도하지 않는 요청을 수행하게 하는 취약점입니다. 즉 공격자는 사용자가 가지고 있는 권한 범위 내에서 악의적인 행위를 할 수 있습니다. 일반적으로 해당 권한은 쿠키와 세션을 이용해서 인증을 하고 있기 때문에 발생하는 일입니다.
하지만 Rest API를 이용한 서버라면, session 기반 인증과는 다르게 stateless하기 때문에 서버에 인증 정보를 보관하지 않습니다. 일반적으로 jwt 같은 토큰을 사용하여 인증하기 때문에 해당 토큰을 Cookie에 저장하지 않는다면 csrf 취약점에 대해서는 어느 정도 안전하다고 말할 수 있습니다.
httpBasic().disable()
세션방식에서 로그인시
, 웹브라우저 쿠키에 세션ID 저장, 요청시
, 헤더에 쿠키(세션아이디)를 들고감
그래서 동일 도메인에서만 허용하도록 httpOnly
를 사용 - ajax나 axios로 요청시, 쿠키를 담아서 보내면 거부하는 기능
httpOnly : http요청이 아니면 쿠키를 건드릴 수 없게함, 아마 SSR으로 추측됨..
http요청이 아닌것 : 스크립트 파일에서.. fetch() . ajax, axios, 이거는 Rest Api 서버로 추측
그래서 요청시 인증하기 위해 나온게(as-is: JSESSION? , to-be: Authentication)
인증시 headers.Authorization에 인증정보를 담고가는 2가지 방식이 있다.
httpBasic
방식Bearer
방식corsFilter()
속성 | 설명 |
---|---|
setAllowCredentials(true) | 자바스크립트 응답을 처리 (ajax, axios) |
addAllowedOrigin("*") | 모든 도메인, 포트 허용 |
addAllowedHeader("*") | 모든 Header허용 - 다른 커스텀 헤더 |
addAllowedMethod("*") | 모든 요청 허용 - GET, POST, PATCH, DELETE |
source.registerCorsConfiguration("/api/*", config) | 해당 경로로 요청시 적용 |
참고
https://www.youtube.com/watch?v=GEv_hw0VOxE&list=PL93mKxaRDidERCyMaobSLkvSPzYtIk0Ah
https://kchanguk.tistory.com/197