How to apply spring security filter only on secured endpoints?

前端 未结 6 580
时光说笑
时光说笑 2020-12-01 05:25

I have the following Spring Security configuration:

    httpSecurity
            .csrf()
            .disable()
            .exceptionHandling()
                     


        
6条回答
  •  Happy的楠姐
    2020-12-01 05:47

    I think I've found a way to solve it. I have JwtTokenAuthenticationProcessingFilter which is an AbstractAuthenticationProcessingFilter. I want it to authenticate request if there is token in the head but do not block the request if failed. All you need is to rewrite the doFilter and invoke the chain.doFilter no matter what the authentication result is(invoking unsuccessfulAuthentication is optional). Here is part of my code.

    public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
    
        private final TokenExtractor tokenExtractor;
    
        @Autowired
        public JwtTokenAuthenticationProcessingFilter(TokenExtractor tokenExtractor, RequestMatcher matcher) {
            super(matcher);
            this.tokenExtractor = tokenExtractor;
        }
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
                ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            if (!this.requiresAuthentication(request, response)) {
                chain.doFilter(request, response);
            } else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Request is to process authentication");
                }
    
                boolean success = true;
    
                Authentication authResult = null;
                try {
                    authResult = this.attemptAuthentication(request, response);
                } catch (InternalAuthenticationServiceException var8) {
                    this.logger.error("An internal error occurred while trying to authenticate the user.", var8);
                    success = false;
                } catch (AuthenticationException var9) {
                    success = false;
                }
    
    
                if (success && null != authResult) {
                    this.successfulAuthentication(request, response, chain, authResult);
                }
    
                // Please ensure that chain.doFilter(request, response) is invoked upon successful authentication. You want
                // processing of the request to advance to the next filter, because very last one filter
                // FilterSecurityInterceptor#doFilter is responsible to actually invoke method in your controller that is
                // handling requested API resource.
                chain.doFilter(request, response);
            }
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
                throws AuthenticationException {
            String tokenPayload = request.getHeader(WebSecurityConfig.AUTHENTICATION_HEADER_NAME);
            RawAccessJwtToken token = new RawAccessJwtToken(tokenExtractor.extract(tokenPayload));
            return getAuthenticationManager().authenticate(new JwtAuthenticationToken(token));
        }
    
        @Override
        protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                                Authentication authResult) throws IOException, ServletException {
            SecurityContext context = SecurityContextHolder.createEmptyContext();
            context.setAuthentication(authResult);
            SecurityContextHolder.setContext(context);
        }
    }
    

    Update at Apr 22

    To register the filter, just add the following code to the WebSecurityConfig

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        private final JwtAuthenticationProvider mJwtAuthenticationProvider;
    
        @Autowired
        public WebSecurityConfig(JwtAuthenticationProvider jwtAuthenticationProvider) {
            this.mJwtAuthenticationProvider = jwtAuthenticationProvider;
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            // When multiple authentication providers are defined, the providers will be queried in the order they’re
            // declared.
            auth.authenticationProvider(mJwtAuthenticationProvider);
        }
    }
    

    In the code, I only revealed the critical part about adding the filter. All this implementation was inspired by this site. Give credit to the author Vladimir Stankovic for his detail explanation.

提交回复
热议问题