java - 有没有办法将 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);
}
}
因此,如果我捕获TokenExpiredException
或SignatureVerificationException
在我的 中AuthFilter
,我想通过消息通知客户:Token is expired
或Token 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);
}
}
我也有一个exceptionHandler
forAuthentication
@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
?
解决方案
推荐阅读
- php - 如果 Schedulertask 由 cronjob 执行,则 getParentKeyFieldName() on null
- android - 折叠工具栏滚动
- android - Delphi Android edit1.setfocus
- java - how to disable "this page is tracking your location"
- ios - IOS原生谷歌广告插上wifi可以正常显示,但是切换到4g就没有广告了
- javafx - TornadoFX: Compare 2 form values in ValidationContext
- python - How to correctly implement StratifiedKFold with RandomizedSearchCV
- android - Volley 给出运行时异常和没有协议的错误 url
- spring - 如何使用 Spring Boot 发送通知 (FCM)
- mysql - 带有 MySQL 迁移的 Django 不起作用