首页 > 解决方案 > 有没有办法将 AuthenticationException 抛出到 AuthenticationEntryPoint 中?

问题描述

我已经实现了 JWT 授权系统。它工作正常,但我应该通知客户他们的令牌已过期。

我配置了我的 Spring Security:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
UserDetailsServiceImpl userDetailsService;

@Autowired
private JwtAuthEntryPoint unauthorizedHandler;

@Bean
public JwtAuthTokenFilter authenticationJwtTokenFilter() {
    return new JwtAuthTokenFilter();
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
    authenticationManagerBuilder
            .userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
}

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

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/login", "/signup", "/email-exist", "/username-exist", "/refresh-tokens", "/public/**").permitAll()
            .antMatchers("/api/trainer/default-config").hasRole(Role.ROLE_ADMIN.name().replace("ROLE_",""))
            .anyRequest().authenticated()
            .and()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler);


    http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    http.addFilterAt(this.corsFilter(), CorsFilter.class);
}
}

因此,如果我捕获TokenExpiredExceptionSignatureVerificationException在我的 中AuthFilter,我想通过消息通知客户:Token is expiredToken is invalid

@Slf4j
public class JwtAuthTokenFilter extends OncePerRequestFilter {

@Autowired
private TokenProvider tokenProvider;

@Autowired
UserDetailsServiceImpl userDetailsService;

@Autowired
JwtAuthEntryPoint authenticationEntryPoint;

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

        String actionToken = tokenProvider.getToken(request);
        if (actionToken !=null) {
            String username = tokenProvider.getUserNameFromJwtToken(actionToken);
            List<GrantedAuthority> authorities = tokenProvider.getAuthoritiesFromJwtToken(actionToken);

            UsernamePasswordAuthenticationToken authentication
                    = new UsernamePasswordAuthenticationToken(userDetailsService.loadUserByUsername(username), null, authorities);
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    } catch (IllegalArgumentException e) {
        logger.error("an error occured during getting username from token", e);
    } catch (TokenExpiredException e) {
        logger.warn("the token is expired and not valid anymore", e);
    } catch(SignatureVerificationException e){
        logger.error("Someone change the token!");
    } catch (Exception e) {
        log.error("Can NOT set user authentication -> Message: {}", e);
    }

    filterChain.doFilter(request, response);
}
}

我也有一个exceptionHandlerforAuthentication

@Component
@Slf4j
public class JwtAuthEntryPoint implements AuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request,
                     HttpServletResponse response,
                     AuthenticationException e) 
                             throws IOException, ServletException {

    log.error(e.getMessage());
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
}
}

如果令牌过期或无效,我总是发送消息Full authentication is required to access this resource。但是我必须通知我的客户有关过期令牌的信息。

我试图commence在我的内部调用方法,JwtAuthTokenFilter但它不起作用:

} catch (TokenExpiredException e) {
     authenticationEntryPoint.commence(request, response, new CredentialsExpiredException(e.getMessage()));
     logger.warn("the token is expired and not valid anymore", e);
} catch(SignatureVerificationException e){
     authenticationEntryPoint.commence(request, response, new BadCredentialsException(e.getMessage()));
     logger.error("Someone change the token!");
}

那么有什么方法可以将我的异常与有关令牌的消息传递到JwtAuthEntryPoint?

标签: javaspringspring-bootspring-security

解决方案


推荐阅读