์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- ๋๊ฐ
- ๊ฐ์ดํ ์ข ๋ญ๊ฐ๋น
- database
- Java
- ๊น๋ฏธ๊ฒฝ์๋งํ์์
- ๊ฐ๋ฐ
- html
- ์๋ฐ์คํฌ๋ฆฝํธ
- K๋ฐฐํฐ๋ฆฌ๋ ๋ณผ๋ฃจ์
- ํ๋ก๊ทธ๋๋ฐ
- ์ค๋ธ์
- ์ ๋ฆฌํธ๋ฆฌํธ
- css
- Python
- ์ฝ๋ฉ
- ์๋ฐ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค
- ์นดํ๋๊ฐ
- ๋ ์
- ํ์ฒ์ ๋ฆฌํธ๋ฆฌํธ
- ์ค๋ผํด
- ๋ฐ์ํ
- ์ํ์ฃผ
- ์นํผ๋ธ๋ฆฌ์ฑ
- ํฐ์คํ ๋ฆฌ์ฑ๋ฆฐ์ง
- ์ฑ
- ์ํ
- ๋ฐฐ์์ ๋ฐฐ์
- JavaScript
- ํ์ด์ฌ
- Today
- Total
JiYoung Dev ๐ฅ
Spring Security ์ ์ฉ๊ธฐ (2) Spring Security Configuration ๋ณธ๋ฌธ
2024.04.22 - [Study/Java] - Spring Security ์ ์ฉ๊ธฐ (1) Spring Security๋?
Spring Security ์ ์ฉ๊ธฐ (1) Spring Security๋?
์๋กญ๊ฒ ํ๋ก์ ํธ๋ฅผ ์์ํ๋ฉด์ ์ ์ฉํด๋ณด๊ณ ์ถ์๋ ๊ธฐ์ ์ค ํ๋์ธ Spring Security. ์ด๋ ํ ๊ธฐ์ ์ด๋ฉฐ ์ด๋ ํ ์๋ฆฌ๋ฅผ ๋ฐํ์ผ๋ก ๋์ํ๋์ง, ๊ทธ๋ฆฌ๊ณ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ ๊ฒ๊น์ง ํ๋ ํ๋ ํฌ์ค
danyoujeong.tistory.com
์ง๋ ํฌ์คํ ์ ์ด์ด ์ด๋ฒ ํฌ์คํ ์์๋ Spring Security Configuration์ ๋ํด ์์๋ณด์๋ค.
ํด๋น ํ๋ก์ ํธ๋ Spring Boot 3.1.11์์ ์งํํ๋ ํ๋ก์ ํธ์ด๋ฉฐ, Spring Security ์ ์ฉ์ ์ํด spring-boot-starter-security ์์กด์ฑ์ ์ถ๊ฐํ๋ค.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
}
SpringBoot 3.1.11 ๋ฒ์ ์ด๋ฏ๋ก security ๋ฒ์ ์ 6.1์ด๋ค.
6.1 ๋ฒ์ ๋ถํฐ๋ WebSecurityConfigureAdapter ํด๋์ค๊ฐ deprecated ๋์ด ํด๋น ํด๋์ค๋ฅผ ์์ ๋ฐ์ config ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ ๋์ SecurityFilterChain์ ๋ฐํํ๊ณ ์ง์ Bean์ผ๋ก ๋ฑ๋กํ๋๋ก ์ค์ ๋ฐฉ๋ฒ์ด ๋ฐ๋์๋ค๊ณ ํ๋ค.
๊ธฐ์กด ์ค์ ๋ฐฉ๋ฒ ์์
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throwd Exception{
http.crsf().disable();
}
}
WebSecurityConfig.java
package com.shop.kns.config;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List;
/**
* Spring Security Configuration
*/
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class WebSecurityConfig {
@Value("${cors.allowed.origins}")
private String allowdOrigins;
private static final String[] WHITE_LIST = {
// Swagger UI v3
"/v3/api-docs/**", "v3/api-docs/**", "/swagger-ui/**", "swagger-ui/**",
// auth
"/api/v1/auth/**",
// test
"/api/v3/api-docs/**", "/api/swagger-ui/**",
};
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable) //csrf ๋นํ์ฑํ
.cors(cors -> cors.configurationSource(corsConfigurationSource())) //cors ๊ตฌ์ฑ
.authorizeHttpRequests(authorize -> authorize //authorize(๊ถํ)
.requestMatchers(WHITE_LIST).permitAll()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.requestMatchers("/shop/**").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class) //์ฌ์ฉ์ ์ ์ ํํฐ ์ถ๊ฐ
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //์ธ์
์์ฑ ์ ์ฑ
.formLogin(login -> login //๋ก๊ทธ์ธ ์ฒ๋ฆฌ ์ค์
.loginPage("/login") //๋ก๊ทธ์ธ ํ์ด์ง
.successHandler(new SimpleUrlAuthenticationSuccessHandler("/shop")) //๋ก๊ทธ์ธ ์ธ์ฆ ์ฑ๊ณต ํ ์ด๋ํ URL
.permitAll()
);
return http.build();
}
/**
* CORS ์ ์ฑ
์ค์
*/
@Bean
public CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(List.of(allowdOrigins)); //ํ์ฉํ URL
corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); //ํ์ฉํ method
corsConfiguration.setAllowedHeaders(List.of("X-Requested-With", "Content-Type", "Authorization", "X-XSRF-token")); //ํ์ฉํ header
corsConfiguration.setAllowCredentials(false); //์๊ฒฉ์ฆ๋ช
(์ฟ ํค, ์ธ์ฆ ํค๋ ๋ฑ) ํ์ฉ ์ฌ๋ถ
corsConfiguration.setMaxAge(3600L); //๋ธ๋ผ์ฐ์ ์๋ต ์บ์ ์๊ฐ(1์๊ฐ)
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return source;
}
}
์ฝ๋ ํ ์ค ํ ์ค ํ์ด ๋ณด์.
@Value("${cors.allowed.origins}")
private String allowdOrigins;
cors ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ url์ ๋ณ๋ ํ๊ฒฝ๋ณ์๋ก ์ง์ ํ์๋ค.
private static final String[] WHITE_LIST = {
// Swagger UI v3
"/v3/api-docs/**", "v3/api-docs/**", "/swagger-ui/**", "swagger-ui/**",
// auth
"/api/v1/auth/**",
// test
"/api/v3/api-docs/**", "/api/swagger-ui/**",
};
์ ๊ทผ ํ์ฉ ๊ฒฝ๋ก๋ฅผ ์ํ String[]์ ๋ฏธ๋ฆฌ ์ ์ํ์๋ค.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
์์์ Spring security๊ฐ ์ ๋ฐ์ดํธ๊ฐ ๋๋ฉด์ ๋ณ๊ฒฝ๋ ๋ถ๋ถ์ด๋ค. SecurityFilterChain์ ๋ฐํํ๊ณ , ์ด๋ฅผ @Bean์ผ๋ก ๋ฑ๋กํ๋ ๋ฐฉ์์ด๋ค.
.csrf(AbstractHttpConfigurer::disable) //csrf ๋นํ์ฑํ
REST API์์ CSRF๋ฅผ disable ํ๋ ์ด์ ๋ jwt๋ฅผ ์ฌ์ฉํ ์์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค. jwt๋ ์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ๊ณผ๋ ๋ค๋ฅด๊ฒ statelessํ๊ธฐ ๋๋ฌธ์ ์๋ฒ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ณด๊ดํ์ง ์๋๋ค. REST API์์ Client๋ ๊ถํ์ด ํ์ํ ์์ฒญ์ ํ๊ธฐ ์ํด์๋ ์์ฒญ์ ํ์ํ ์ธ์ฆ ์ ๋ณด๋(OAuth2, jwt ํ ํฐ ๋ฑ)์ ํฌํจ์์ผ์ผ ํ๋ค. ๋ฐ๋ผ์ ์ธ์ฆ์ ๋ณด๋ฅผ ์๋ฒ์ ์ ์ฅํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ตณ์ด ๋ถํ์ํ csrf ์ฝ๋๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค.
.authorizeHttpRequests(authorize -> authorize //authorize(๊ถํ)
.requestMatchers(WHITE_LIST).permitAll()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.anyRequest().authenticated()
)
ํ์ด์ง์ ๋ํ ๊ถํ ์ค์ ์ด๋ค. WHITE_LIST๋ก ๋ค์ด์ค๋ ์์ฒญ์ ๋ชจ๋ ํ์ฉ์ผ๋ก ์ค์ ํ์๋ค.
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
์์ ์ฝ๋๋ PreFlight ์์ฒญ์ ๋ํด ๋ชจ๋ ํ์ฉ ํ๊ฒ ๋ค๋ ์ค์ ์ด๋ค. Cors pre-flight ์์ฒญ์ ์ค์ ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฒ๋ก ์ถ๊ฐ๋ก ๋ณด๋ด๋ ์ถ๊ฐ ์์ฒญ์ด๋ค. ์ด ์์ฒญ์ ๋ธ๋ผ์ฐ์ ๊ฐ ํ์ฌ ๋๋ฉ์ธ์์ ๋ค๋ฅธ ์ถ์ฒ(origin)๋ก์ ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ ์, ์๋ฒ๊ฐ ํด๋น ์์ฒญ์ ์๋ฝํ ์ ์๋์ง ํ์ธํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
Cors pre-flight ์์ฒญ์ ์ฃผ๋ก ์๋์ ๊ฐ์ ๊ฒฝ์ฐ์ ๋ฐ์ํ๋ค. 1. ๋ธ๋ผ์ฐ์ ์์ Ajax ์์ฒญ์ ๋ณด๋ผ ๋, ํด๋น ์์ฒญ์ด ๊ฐ์ ์ถ์ฒ๊ฐ ์๋ ๋ค๋ฅธ ๋๋ฉ์ธ์ผ๋ก ๋ณด๋ด๋ ๊ฒฝ์ฐ2. ์์ฒญ์ ํน์ ํ HTTP ๋ฉ์๋๋ ํค๋๊ฐ ํฌํจ๋์ด ์๋ ๊ฒฝ์ฐ. ์๋ฅผ ๋ค์ด 'PUT', 'DELETE', 'Content-Type' ๋ฑ
.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class)
UsernamePasswordAuthenticationFilter ์ ์ฉ ์ ์ jwtAuthorizationFilter๋ฅผ ์ ์ฉํ๋ ๋ถ๋ถ์ด๋ค. Spring Security์์๋ BasicAuthenticationFilter๋ฅผ ์ ๊ณตํ๊ณ ์์ง๋ง, ํด๋น ํํฐ๋ ์ฌ์ฉ์์ ID์ ๋น๋ฐ๋ฒํธ๋ฅผ ํค๋์ ์ ๋ฌํ๋ ๋ฐฉ์์ผ๋ก jwt ์ธ์ฆ ๋ฐฉ์๊ณผ ์ถฉ๋ํ๋ฏ๋ก ์ด๋ฅผ disableํ๋ ๊ฒ์ด ์ข๋ค.
UsernamePasswordAuthenticationFilter
1. ์ฃผ๋ก ์ฌ์ฉ์๊ฐ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ์ฌ ๋ก๊ทธ์ธํ๋ ๋ฐ ์ฌ์ฉ2. ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ํ์ด์ง์ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ์ถํ๋ฉด, ์ด ํํฐ๊ฐ ํด๋น ์ ๋ณด๋ฅผ ๋ฐ์์ Spring Security์ ์ธ์ฆ ๋งค๋์ ์๊ฒ ์ ๋ฌํ๋ค. ์ธ์ฆ ๋งค๋์ ๋ ์ ๊ณต๋ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๋ฅผ ์ธ์ฆํ๊ณ , ์ธ์ฆ์ด ์ฑ๊ณตํ๋ฉด ์ธ์ฆ๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์์ฑํ๋ค.
BasicAuthenticationFilter
1. HTTP Basic ์ธ์ฆ ์คํด์ ์ฒ๋ฆฌํ๋๋ฐ ์ฌ์ฉ๋๋ค. 2. ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ๋ณด๋ผ ๋ Authorization ํค๋์ Base64๋ก ์ธ์ฝ๋ฉ๋ "username:password"๋ฅผ ํฌํจํ์ฌ ๋ณด๋ด๋ฉด, ์ด ํํฐ๊ฐ ์ด๋ฅผ ์ถ์ถํ๊ณ ์ธ์ฆ ๋งค๋์ ์๊ฒ ์ ๋ฌํ๋ค. ์ฃผ๋ก Restful API์์ ์ฌ์ฉ๋๋ฉฐ, ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ๋ณด๋ผ ๋ HTTP Basic ์ธ์ฆ ํค๋๋ฅผ ํฌํจํ์ฌ ๋ณด๋ด๋ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
UsernamePasswordAuthenticationFilter๋ ์ฌ์ฉ์๊ฐ ์ง์ ๋ก๊ทธ์ธ ํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉ๋๊ณ , BasicAuthenticationFilter๋ ํด๋ผ์ด์ธํธ๊ฐ HTTP Basic ์ธ์ฆ์ ์ฌ์ฉํ์ฌ ์์ฒญ์ ๋ณด๋ด๋ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
์ผ๋ฐ์ ์ผ๋ก jwt๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ฌ์ฉ์๊ฐ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ์ถํ๋ ๋ฐฉ์์ด ์๋๊ธฐ ๋๋ฌธ์ UsernamePasswordAuthenticationFilter๋ฅผ ์ฌ์ฉํ๋ค.
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //์ธ์
์์ฑ ์ ์ฑ
JWT๋ฅผ ์ฌ์ฉํ ์์ ์ด๋ฏ๋ก STATELESS ์ฆ, ์ธ์ ์ ์ฌ์ฉํ์ง ์๊ฒ ๋ค๋ ์ค์ ์ ํ๋ค.
.formLogin(login -> login //๋ก๊ทธ์ธ ์ฒ๋ฆฌ ์ค์
.loginPage("/login") //๋ก๊ทธ์ธ ํ์ด์ง
.successHandler(new SimpleUrlAuthenticationSuccessHandler("/shop")) //๋ก๊ทธ์ธ ์ธ์ฆ ์ฑ๊ณต ํ ์ด๋ํ URL
.permitAll()
);
๋ก๊ทธ์ธ ์ฒ๋ฆฌ์ ๋ํ ์ค์ ์ด๋ค.
์ฐธ๊ณ ์๋ฃ
[spring] spring security๋ฅผ ์ด์ฉํ JWT ๋ก๊ทธ์ธ
๊ธฐ์กด์๋ ์ธ์ /์ฟ ํค ๋ฐฉ์์ผ๋ก ๋ก๊ทธ์ธ์ ๊ตฌํํ์์ง๋ง ๋ค์ค ์๋ฒํ๊ฒฝ์์์ ์๋ฒ๊ฐ ์ธ์ ๊ณต์ ๋ฌธ์ , ์ฑ์ผ๋ก ํ์ฅํ์๋ clinet์ ํ๊ฒฝ ์ฐจ์ด, Front-end์์ ๋ก์ปฌํ๊ฒฝ์ผ๋ก ํ ์คํธํ ๋ Back-end ์๋ฒ์์
sbl133.tistory.com
'Study > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring Security ์ ์ฉ๊ธฐ (5) Spring Security Authentication ๋์์๋ฆฌ (0) | 2024.05.05 |
---|---|
Spring Security ์ ์ฉ๊ธฐ (3) JWT(JSON Web Tokens) ๊ฐ๋ (0) | 2024.04.29 |
Spring Security ์ ์ฉ๊ธฐ (1) Spring Security๋? (0) | 2024.04.22 |
๊ธฐ์ ๋ฉด์ ์ค๋น 5. Java ์ง๋ฌธ ์ ๋ฆฌ (1) | 2023.11.18 |
๊ธฐ์ ๋ฉด์ ์ค๋น 4. ์๋ฐ ๋ณ์์ ๋ฐ์ดํฐ ํ์ Primitive type & Reference type (1) | 2023.11.08 |