我已经实现了jwt授权系统。它工作正常,但我应该通知客户端,他们的令牌已过期。
我配置了spring安全:
@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` 为了 `Authentication` ```
@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
?
暂无答案!
目前还没有任何答案,快来回答吧!