[SPRING] Java Config를 사용하는 Spring Security 커스텀 인증 필터
SPRINGJava Config를 사용하는 Spring Security 커스텀 인증 필터
기본 웹 애플리케이션에서 Java config를 사용하여 Spring Security를 구성하여 URL 요청 매개 변수에 제공된 암호화 된 토큰을 사용하여 외부 웹 서비스에 대해 인증하려고합니다.
나는 (내가 생각하기에) Login Portal의 요청을 차단하는 보안 필터 (모두가 / 인증)를 사용하기를 원한다면 필터는 AuthenticationProvider를 사용하여 인증 프로세스의 bussiness 논리를 처리합니다.
로그인 포털 -> 리다이렉트 '\ authenticate'(+ 토큰) -> 인증 토큰을 다시 로그인 포털 (WS) -> 성공하면 역할 및 설정 사용자가됩니다.
필터를 만들었습니다 ..
@Component
public final class OEWebTokenFilter extends GenericFilterBean {
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
OEToken token = extractToken(request);
// dump token into security context (for authentication-provider to pick up)
SecurityContextHolder.getContext().setAuthentication(token);
}
}
chain.doFilter(request, response);
}
AuthenticationProvider ...
@Component
public final class OEWebTokenAuthenticationProvider implements AuthenticationProvider {
@Autowired
private WebTokenService webTokenService;
@Override
public boolean supports(final Class<?> authentication) {
return OEWebToken.class.isAssignableFrom(authentication);
}
@Override
public Authentication authenticate(final Authentication authentication) {
if (!(authentication instanceof OEWebToken)) {
throw new AuthenticationServiceException("expecting a OEWebToken, got " + authentication);
}
try {
// validate token locally
OEWebToken token = (OEWebToken) authentication;
checkAccessToken(token);
// validate token remotely
webTokenService.validateToken(token);
// obtain user info from the token
User userFromToken = webTokenService.obtainUserInfo(token);
// obtain the user from the db
User userFromDB = userDao.findByUserName(userFromToken.getUsername());
// validate the user status
checkUserStatus(userFromDB);
// update ncss db with values from OE
updateUserInDb(userFromToken, userFromDB);
// determine access rights
List<GrantedAuthority> roles = determineRoles(userFromDB);
// put account into security context (for controllers to use)
return new AuthenticatedAccount(userFromDB, roles);
} catch (AuthenticationException e) {
throw e;
} catch (Exception e) {
// stop non-AuthenticationExceptions. otherwise full stacktraces returned to the requester
throw new AuthenticationServiceException("Internal error occurred");
}
}
그리고 내 Spring Security Config
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
OESettings oeSettings;
@Bean(name="oeAuthenticationService")
public AuthenticationService oeAuthenticationService() throws AuthenticationServiceException {
return new AuthenticationServiceImpl(new OEAuthenticationServiceImpl(), oeSettings.getAuthenticateUrl(), oeSettings.getApplicationKey());
}
@Autowired
private OEWebTokenFilter tokenFilter;
@Autowired
private OEWebTokenAuthenticationProvider tokenAuthenticationProvider;
@Autowired
private OEWebTokenEntryPoint tokenEntryPoint;
@Bean(name="authenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(tokenAuthenticationProvider);
}
@Bean
public FilterRegistrationBean filterRegistrationBean () {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(tokenFilter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate**").permitAll()
.antMatchers("/resources/**").hasAuthority("ROLE_USER")
.antMatchers("/home**").hasAuthority("ROLE_USER")
.antMatchers("/personSearch**").hasAuthority("ROLE_ADMIN")
// Spring Boot actuator endpoints
.antMatchers("/autoconfig**").hasAuthority("ROLE_ADMIN")
.antMatchers("/beans**").hasAuthority("ROLE_ADMIN")
.antMatchers("/configprops**").hasAuthority("ROLE_ADMIN")
.antMatchers("/dump**").hasAuthority("ROLE_ADMIN")
.antMatchers("/env**").hasAuthority("ROLE_ADMIN")
.antMatchers("/health**").hasAuthority("ROLE_ADMIN")
.antMatchers("/info**").hasAuthority("ROLE_ADMIN")
.antMatchers("/mappings**").hasAuthority("ROLE_ADMIN")
.antMatchers("/metrics**").hasAuthority("ROLE_ADMIN")
.antMatchers("/trace**").hasAuthority("ROLE_ADMIN")
.and()
.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(tokenAuthenticationProvider)
.antMatcher("/authenticate/**")
.exceptionHandling().authenticationEntryPoint(tokenEntryPoint)
.and()
.logout().logoutSuccessUrl(oeSettings.getUrl());
}
}
내 문제는 내 SpringConfig 클래스의 필터 구성입니다. 요청이 / authenticate URL에 대한 것일 때만 필터가 적용되도록하고 필터 구성에 .antMatcher ( "/ authenticate / **")를 추가했습니다.
.and()
.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(tokenAuthenticationProvider)
.antMatcher("/authenticate/**")
.exceptionHandling().authenticationEntryPoint(tokenEntryPoint)
다른 모든 URL의이 줄을 더 이상 보안하지 않으면 수동으로 인증없이 / home으로 이동할 수 있으며 줄을 제거하고 / home이 인증됩니다.
특정 URL에만 적용 할 수있는 필터를 선언해야합니까?
다른 URL의 보안을 유지하면서 어떻게 구현할 수 있습니까?
해결법
-
==============================
1.나는 인증 공급자를 보류하기 전에 필터의 인증 상태를 검사하여 문제를 해결했다.
나는 인증 공급자를 보류하기 전에 필터의 인증 상태를 검사하여 문제를 해결했다.
구성
.and() .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class) .authenticationProvider(tokenAuthenticationProvider) .exceptionHandling().authenticationEntryPoint(tokenEntryPoint)
필터
@Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { logger.debug(this + "received authentication request from " + request.getRemoteHost() + " to " + request.getLocalName()); if (request instanceof HttpServletRequest) { if (isAuthenticationRequired()) { // extract token from header OEWebToken token = extractToken(request); // dump token into security context (for authentication-provider to pick up) SecurityContextHolder.getContext().setAuthentication(token); } else { logger.debug("session already contained valid Authentication - not checking again"); } } chain.doFilter(request, response); } private boolean isAuthenticationRequired() { // apparently filters have to check this themselves. So make sure they have a proper AuthenticatedAccount in their session. Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); if ((existingAuth == null) || !existingAuth.isAuthenticated()) { return true; } if (!(existingAuth instanceof AuthenticatedAccount)) { return true; } // current session already authenticated return false; }
from https://stackoverflow.com/questions/27507862/spring-security-custom-authentication-filter-using-java-config by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] PropertyPlaceholderConfigurer와 함께 사용할 환경 별 특성을로드 하시겠습니까? (0) | 2019.03.03 |
---|---|
[SPRING] spring-boot에서 hibernate.format_sql을 설정하는 방법은? (0) | 2019.03.03 |
[SPRING] 테스트 @ 봄에 스케줄 (0) | 2019.03.03 |
[SPRING] 하이버 네이트 세션이 쓰레드에 바인드되지 않았고, 컨피규레이션은 비 - 트랜젝션 세션의 생성을 허용하지 않는다. (0) | 2019.03.03 |
[SPRING] 스프링 부트를 사용하지 않고 스프링 휴식 서비스 만들기 (0) | 2019.03.03 |