복붙노트

[SPRING] Java Config를 사용하는 Spring Security 커스텀 인증 필터

SPRING

Java 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. ==============================

    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;
    }
    
  2. from https://stackoverflow.com/questions/27507862/spring-security-custom-authentication-filter-using-java-config by cc-by-sa and MIT license