Skip to content

Commit 93887df

Browse files
authored
Merge pull request #21 from DMU-DebugVisual/feat/jwt-filter-refactor
feat: 특정 API에만 JWT 인증이 적용되도록 SecurityConfig 수정 (#20)
2 parents 8a6a66a + 3c76c49 commit 93887df

File tree

1 file changed

+64
-12
lines changed

1 file changed

+64
-12
lines changed

src/main/java/com/dmu/debug_visual/config/SecurityConfig.java

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
import org.springframework.beans.factory.annotation.Value;
66
import org.springframework.context.annotation.Bean;
77
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.context.annotation.Profile;
9+
import org.springframework.core.annotation.Order;
810
import org.springframework.http.HttpHeaders;
911
import org.springframework.http.MediaType;
1012
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
1113
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
14+
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
1215
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
1316
import org.springframework.security.crypto.password.PasswordEncoder;
1417
import org.springframework.security.web.SecurityFilterChain;
@@ -32,28 +35,79 @@ public class SecurityConfig {
3235
@Value("${compiler.python.url}")
3336
private String compilerPythonUrl;
3437

38+
// 1. JWT 인증이 필요한 API를 위한 필터 체인 (우선순위 1)
3539
@Bean
36-
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
40+
@Order(1)
41+
@Profile("!dev")
42+
public SecurityFilterChain jwtFilterChain(HttpSecurity http) throws Exception {
3743
http
44+
.securityMatcher("/api/posts/**", "/api/notifications/**", "/api/admin/**", "/api/report/**", "/api/comments/**") // 이 경로들에 대해서만 이 필터 체인을 적용
3845
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
39-
.csrf(csrf -> csrf.disable())
46+
.csrf(AbstractHttpConfigurer::disable)
4047
.authorizeHttpRequests(auth -> auth
48+
.requestMatchers("/api/admin/**").hasRole("ADMIN")
49+
.requestMatchers("/api/posts/**").hasAnyRole("USER", "ADMIN")
50+
.requestMatchers("/api/notifications/**").hasAnyRole("USER", "ADMIN")
51+
.requestMatchers("/api/report/**").hasAnyRole("USER", "ADMIN")
52+
.requestMatchers("/api/comments/**").hasAnyRole("USER", "ADMIN")
53+
.anyRequest().authenticated()
54+
)
55+
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider, userRepository),
56+
UsernamePasswordAuthenticationFilter.class)
57+
.formLogin(AbstractHttpConfigurer::disable)
58+
.httpBasic(AbstractHttpConfigurer::disable);
59+
60+
return http.build();
61+
}
62+
63+
// 2. JWT 인증이 필요 없는 API 및 기타 경로를 위한 필터 체인 (우선순위 2)
64+
@Bean
65+
@Order(2)
66+
@Profile("!dev")
67+
public SecurityFilterChain publicFilterChain(HttpSecurity http) throws Exception {
68+
http
69+
// securityMatcher를 지정하지 않으면 나머지 모든 요청을 처리합니다.
70+
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
71+
.csrf(AbstractHttpConfigurer::disable)
72+
.authorizeHttpRequests(auth -> auth
73+
// 로그인, 회원가입, Swagger 등 인증이 필요 없는 경로는 여기서 permitAll() 처리
4174
.requestMatchers(
4275
"/api/users/login",
4376
"/api/users/signup",
4477
"/swagger-ui/**",
45-
"/v3/api-docs/**"
78+
"/v3/api-docs/**",
79+
"/api/code/**"
4680
).permitAll()
47-
.requestMatchers("/api/admin/**").hasRole("ADMIN")
48-
.requestMatchers("/api/posts/**").hasAnyRole("USER", "ADMIN")
49-
.requestMatchers("/api/notifications/**").hasAnyRole("USER", "ADMIN")
81+
.anyRequest().permitAll()
82+
);
83+
84+
return http.build();
85+
}
86+
87+
// "dev" 프로파일에서 사용할 보안 설정
88+
@Bean
89+
@Profile("dev")
90+
public SecurityFilterChain devSecurityFilterChain(HttpSecurity http) throws Exception {
91+
http
92+
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
93+
.csrf(AbstractHttpConfigurer::disable)
94+
.authorizeHttpRequests(auth -> auth
95+
// dev 환경에서 인증 없이 접근을 허용할 경로
96+
.requestMatchers(
97+
"/api/admin/**",
98+
"/api/users/login",
99+
"/api/users/signup",
100+
"/swagger-ui/**",
101+
"/v3/api-docs/**",
102+
"/api/code/**"
103+
).permitAll()
104+
// 그 외 모든 요청은 인증을 요구하도록 설정 (!dev 환경과 유사하게)
50105
.anyRequest().authenticated()
51106
)
52107
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider, userRepository),
53108
UsernamePasswordAuthenticationFilter.class)
54-
.formLogin(form -> form.disable())
55-
.httpBasic(basic -> basic.disable());
56-
109+
.formLogin(AbstractHttpConfigurer::disable)
110+
.httpBasic(AbstractHttpConfigurer::disable);
57111
return http.build();
58112
}
59113

@@ -74,8 +128,6 @@ public WebClient webClient() {
74128
public CorsConfigurationSource corsConfigurationSource() {
75129
CorsConfiguration config = new CorsConfiguration();
76130
config.setAllowedOriginPatterns(List.of("*"));
77-
// 또는 특정 도메인만 허용할 경우:
78-
// config.setAllowedOrigins(List.of("https://zivorp.com", "http://zivorp.com"));
79131
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
80132
config.setAllowedHeaders(List.of("*"));
81133
config.setAllowCredentials(true);
@@ -84,4 +136,4 @@ public CorsConfigurationSource corsConfigurationSource() {
84136
source.registerCorsConfiguration("/**", config);
85137
return source;
86138
}
87-
}
139+
}

0 commit comments

Comments
 (0)