Custom Filter 구현
- Spring Security Custom Filter 를 만들 수 있다.
- 기본적은 서블릿 필터를 만드는 것과 동일하다.
- 아래와 같이 구현할 수 있다.
public class LoggingFilter extends GenericFilter {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
chain.doFilter(request, response);
stopWatch.stop();
logger.info(stopWatch.prettyPrint());
}
}
- GenericFilter 를 상속받으면 스프링에 친화적인 필터를 만들 수 있다.
- OncePerRequestFilter 를 상속받아서 구현하는 경우도 많다.
- 아래와 같이 어떤 위치에서 실행될 것인지를 설정해 줄 수 있다.
http.addFilterAfter(new LoggingFilter(), UsernamePasswordAuthenticationFilter.class);
- UsernamePasswordAuthenticationFilter 뒤에 커스텀해서 만든 LoggingFilter 를 위치시킬 수 있다.
- chain,doFilter(request, response); -> 다음 필터로 넘어기는 코드이다. -> 이 코드를 적어줘야 다음 필터로 넘어간다.
/**
* 테스트 유저인 경우에는 어드민과 유저 권한 모두를 줍니다.
*/
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("tester")) {
return new UsernamePasswordAuthenticationToken(
user,
null,
Stream.of("ROLE_ADMIN", "ROLE_USER")
.map(authority -> (GrantedAuthority) () -> authority)
.collect(Collectors.toList())
);
}
return authentication;
}
}
- 위와 같이 테스트 유저인 경우 모든 권한을 부여하는 로직을 필터로 구현할 수 있다.
// stopwath filter
http.addFilterAfter(
new LoggingFilter(),
UsernamePasswordAuthenticationFilter.class
);
// tester authentication filter
http.addFilterBefore(
new TesterAuthenticationFilter(this.authenticationManager()),
LoggingFilter.class
);
- 위와 같이 먼저 만든 LoggingFilter 뒤에 위치 시킬 수 있다.
- 만약 앞에 위치시키고 싶다면? -> http.addFilterAfter 를 사용하면 된다.
REFERENCES
- 백기선님의 스프링 시큐리티
- 안성훈님의 스프링 시큐리티