Java Config를 사용한 Spring Security 사용자 지정 인증 필터
기본 웹 어플리케이션에서 Java config를 사용하여 URL 요청 파라미터에 제공된 암호화된 토큰을 사용하여 외부 웹 서비스에 대한 인증을 수행하도록 Spring Security를 구성하려고 합니다.
Login Portal(로그인 포털)의 요청을 가로채는 보안 필터(모두 인증/인증)가 있으면 좋겠습니다. 이 필터는 Authentication Provider(인증 공급자)를 사용하여 인증 프로세스의 비즈니스 로직을 처리합니다.
로그인 포털 --> '\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);
}
인증 공급자...
@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");
}
}
그리고 나의 스프링 보안 구성
@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 클래스의 필터 구성입니다.필터 구성에 .antMatcher("/authenticate/**")를 추가하여 /authenticate URL에 대한 요청일 때만 필터가 적용되도록 합니다.
.and()
.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(tokenAuthenticationProvider)
.antMatcher("/authenticate/**")
.exceptionHandling().authenticationEntryPoint(tokenEntryPoint)
다른 모든 URL에 이 줄이 있으면 인증하지 않고 수동으로 /home으로 이동하여 줄을 제거하면 /home이 인증됩니다.
특정 URL에만 적용 가능한 필터를 선언해야 합니까?
다른 URL의 보안을 유지하면서 이를 구현하려면 어떻게 해야 합니까?
인증 공급자를 참여시키기 전에 필터에서 인증 상태를 확인하여 문제를 해결했습니다. ..
구성
.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;
}
언급URL : https://stackoverflow.com/questions/27507862/spring-security-custom-authentication-filter-using-java-config
'programing' 카테고리의 다른 글
FALSE와 TRUE의 이상한 정의, 왜? (0) | 2023.11.02 |
---|---|
왜 C 언어들은 if 문장에서 간단한 조건 주위에 부모를 필요로 합니까? (0) | 2023.11.02 |
액체 베이스:오류 업데이트 함수/저장 프로시저 mysql (0) | 2023.11.02 |
JQuery event.preventDefault()가 설정된 경우 window.open에 팝업 차단 무시 (0) | 2023.10.23 |
Flower : 플레이 스토어용 버전 코드 업그레이드 (0) | 2023.10.23 |