From 4f13595479ed65a49beecd95f464d4b6b58fea67 Mon Sep 17 00:00:00 2001 From: Daeil Choi Date: Mon, 6 Feb 2023 17:42:02 +0900 Subject: [PATCH] =?UTF-8?q?Add=20custom=20filter=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/SecurityConfig.java | 34 ++++++++++++--- .../filter/StopwatchFilter.java | 27 ++++++++++++ .../filter/TesterAuthenticationFilter.java | 42 +++++++++++++++++++ 3 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/example/springsecuritystudy/filter/StopwatchFilter.java create mode 100644 src/main/java/com/example/springsecuritystudy/filter/TesterAuthenticationFilter.java diff --git a/src/main/java/com/example/springsecuritystudy/config/SecurityConfig.java b/src/main/java/com/example/springsecuritystudy/config/SecurityConfig.java index 48f4c1f..8afc814 100644 --- a/src/main/java/com/example/springsecuritystudy/config/SecurityConfig.java +++ b/src/main/java/com/example/springsecuritystudy/config/SecurityConfig.java @@ -1,25 +1,46 @@ package com.example.springsecuritystudy.config; +import com.example.springsecuritystudy.filter.StopwatchFilter; +import com.example.springsecuritystudy.filter.TesterAuthenticationFilter; +import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.security.servlet.PathRequest; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 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.WebSecurityCustomizer; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import lombok.RequiredArgsConstructor; - /** * Security 설정 Config */ -@EnableWebSecurity +@EnableWebSecurity(debug = true) @RequiredArgsConstructor public class SecurityConfig { + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + + @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + // stopwatch filter + http.addFilterBefore( + new StopwatchFilter(), + WebAsyncManagerIntegrationFilter.class + ); + // tester authentication filter + http.addFilterBefore( + new TesterAuthenticationFilter(authenticationManager(http.getSharedObject(AuthenticationConfiguration.class))), + UsernamePasswordAuthenticationFilter.class + ); http .httpBasic().disable() .csrf(); @@ -27,7 +48,7 @@ public class SecurityConfig { .rememberMe(); http .authorizeHttpRequests(auth -> auth - .antMatchers("/", "/home", "/signup", "/h2-console/**").permitAll() + .antMatchers("/", "/home", "/signup").permitAll() .antMatchers("/note").hasRole("USER") .antMatchers("/admin").hasRole("ADMIN") .antMatchers(HttpMethod.POST, "/notice").hasRole("ADMIN") @@ -53,7 +74,10 @@ public class SecurityConfig { @Bean public WebSecurityCustomizer webSecurityCustomizer() { // 정적 리소스 spring security 대상에서 제외 - return (web) -> web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations()); + return (web) -> web.ignoring() + .antMatchers("/h2-console/**") + .requestMatchers(PathRequest.toStaticResources().atCommonLocations()) + ; } } diff --git a/src/main/java/com/example/springsecuritystudy/filter/StopwatchFilter.java b/src/main/java/com/example/springsecuritystudy/filter/StopwatchFilter.java new file mode 100644 index 0000000..703aa69 --- /dev/null +++ b/src/main/java/com/example/springsecuritystudy/filter/StopwatchFilter.java @@ -0,0 +1,27 @@ +package com.example.springsecuritystudy.filter; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.util.StopWatch; +import org.springframework.web.filter.OncePerRequestFilter; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class StopwatchFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + StopWatch stopWatch = new StopWatch(request.getServletPath()); + stopWatch.start(); + filterChain.doFilter(request, response); + stopWatch.stop(); + // Log StopWatch '/login' : running time = 150545041 ns + log.info(stopWatch.shortSummary()); + } +} diff --git a/src/main/java/com/example/springsecuritystudy/filter/TesterAuthenticationFilter.java b/src/main/java/com/example/springsecuritystudy/filter/TesterAuthenticationFilter.java new file mode 100644 index 0000000..17ebcda --- /dev/null +++ b/src/main/java/com/example/springsecuritystudy/filter/TesterAuthenticationFilter.java @@ -0,0 +1,42 @@ +package com.example.springsecuritystudy.filter; + +import com.example.springsecuritystudy.user.User; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 테스트 유저인 경우에는 어드민과 유저 권한 모두를 줍니다. + */ +public class TesterAuthenticationFilter extends UsernamePasswordAuthenticationFilter { + + public TesterAuthenticationFilter(AuthenticationManager authenticationManager) { + super(authenticationManager); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws + AuthenticationException { + Authentication authentication = super.attemptAuthentication(request, response); + User user = (User) authentication.getPrincipal(); + if (user.getUsername().startsWith("test")) { + // 테스트 유저인 경우 어드민과 유저 권한 모두 부여 + return new UsernamePasswordAuthenticationToken( + user, + null, + Stream.of("ROLE_ADMIN", "ROLE_USER") + .map(authority -> (GrantedAuthority) () -> authority) + .collect(Collectors.toList()) + ); + } + return authentication; + } +}