使用JWT的Spring安全性,如何使用JwtAuthenticationFilter排除某些端点(如/ login)的身份验证?

时间:2018-05-23 09:36:29

标签: spring-boot spring-security jwt

我想排除/登录网址被spring security认证。 我的配置类看起来像'

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and().authorizeRequests().antMatchers("/v1/pricing/login").permitAll()
            .antMatchers("v1/pricing/**").authenticated().and()
    .addFilterBefore(corsFilter,UsernamePasswordAuthenticationFilter.class)
    .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

}


 @Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/v1/pricing/login");

}

JwtAuthenticationFilter看起来像 - 评论了异常部分,因为它也开始在登录中抛出异常

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {


private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

@Autowired
JwtTokenProvider jwtTokenProvider;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {


    String jwt = getJwtFromRequest(request);

    if (StringUtils.hasText(jwt) && jwtTokenProvider.validateToken(jwt)) {

        String[] userInfo = jwtTokenProvider.getUserDetailsFromJWT(jwt);
        UserDetails userDetails = new UserPrincipal(Long.parseLong(userInfo[0]), userInfo[1], userInfo[2], null,
                userInfo[3]);
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(userDetails, null, null);
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

    }


    filterChain.doFilter(request, response);

}

private String getJwtFromRequest(HttpServletRequest request) {

    String token = request.getHeader("Authorization");
    if (StringUtils.hasText(token)) {
        return token;
    } /*else {
        throw new AuthenticationServiceException("Authorization header cannot be blank!");
    }*/
    return null;
}

}

使用/ v1 / pricing / login的任何请求仍然会转到JWtAuthentication过滤器并失败。

1 个答案:

答案 0 :(得分:0)

JwtTokenAuthenticationProcessingFilter过滤器配置为跳过以下端点:/ api / auth / login和/ api / auth / token。这是通过RequestMatcher的SkipPathRequestMatcher实现实现的。

public class SkipPathRequestMatcher implements RequestMatcher {
private OrRequestMatcher matchers;
private RequestMatcher processingMatcher;

public SkipPathRequestMatcher(List<String> pathsToSkip, String processingPath) {
    Assert.notNull(pathsToSkip);
    List<RequestMatcher> m = pathsToSkip.stream().map(path -> new AntPathRequestMatcher(path)).collect(Collectors.toList());
    matchers = new OrRequestMatcher(m);
    processingMatcher = new AntPathRequestMatcher(processingPath);
}

@Override
public boolean matches(HttpServletRequest request) {
    if (matchers.matches(request)) {
        return false;
    }
    return processingMatcher.matches(request) ? true : false;
}}

然后致电:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {  
    public static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization";
    public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login";
    public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**";
    public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token";

protected JwtTokenAuthenticationProcessingFilter buildJwtTokenAuthenticationProcessingFilter() throws Exception {
        List<String> pathsToSkip = Arrays.asList(TOKEN_REFRESH_ENTRY_POINT, FORM_BASED_LOGIN_ENTRY_POINT);
        SkipPathRequestMatcher matcher = new SkipPathRequestMatcher(pathsToSkip, TOKEN_BASED_AUTH_ENTRY_POINT);
        JwtTokenAuthenticationProcessingFilter filter 
            = new JwtTokenAuthenticationProcessingFilter(failureHandler, tokenExtractor, matcher);
        filter.setAuthenticationManager(this.authenticationManager);
        return filter;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(ajaxAuthenticationProvider);
        auth.authenticationProvider(jwtAuthenticationProvider);
    }

    @Bean
    protected BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable() // We don't need CSRF for JWT based authentication
        .exceptionHandling()
        .authenticationEntryPoint(this.authenticationEntryPoint)

        .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

        .and()
            .authorizeRequests()
                .antMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll() // Login end-point
                .antMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point
                .antMatchers("/console").permitAll() // H2 Console Dash-board - only for testing
        .and()
            .authorizeRequests()
                .antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected API End-points
        .and()
            .addFilterBefore(buildAjaxLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}