以下是发生的情况:服务器接受 jwt 身份验证令牌,如果令牌存在于标头中,它首先检查令牌,然后才允许它访问资源,甚至是公共资源。并且,如果令牌过期或无效,则服务器会抛出身份验证错误并向客户端返回 401:
@RequiredArgsConstructor
public class JwtTokenFilter extends GenericFilterBean {
private final JwtTokenProvider jwtTokenProvider;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String token = jwtTokenProvider.retrieveAccessToken((HttpServletRequest) servletRequest);
try {
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication authentication = jwtTokenProvider.getAuthentication(token);
if (authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
} catch (JwtAuthenticationException ex) {
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletResponse.sendError(HttpStatus.UNAUTHORIZED.value(), ex.getMessage());
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
}
=========================
@RequiredArgsConstructor
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final JwtTokenProvider provider;
@Override
public void configure(HttpSecurity builder) throws Exception {
JwtTokenFilter filter = new JwtTokenFilter(provider);
builder.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}
}
这是通过覆盖方法解决的WebSecurityConfigurerAdapter:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/publuc_urls");
}
很好,但是当尝试从第三方站点(在我的情况下,是发出 ajax 请求的客户端)获取资源时 - 发生错误
虽然,我提请您注意,对于上面配置中未忽略的地址,只要它CorsFilter存在,一切正常。这是配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.addFilterBefore(new CorsFilter(corsConfigurationSource()), SessionManagementFilter.class)
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/hello", "/login", "/register", "/refresh_token").permitAll()
.anyRequest().authenticated()
.and()
.apply(new JwtConfigurer(provider));
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config.applyPermitDefaultValues());
return source;
}
也就是说,如果这个地址被忽略,那么它不仅会飞过 jwt 过滤器,还会飞过 cors 过滤器。
需要实现一个刷新令牌(客户端向服务器发送一个过期的访问令牌和一个刷新令牌)。它无法通过令牌过滤器,因为标头中的访问令牌已过期,并且它无法通过 cors 过滤器,因为请求是从左侧站点发出的。
可以做些什么呢?

忽略所有过滤器(
SessionManagementFilter、CorsFilter等UsernamePasswordAuthenticationFilter)但是过滤器的某些url也不可能例外,
JwtTokenFilter没有这样的工具。但是您可以并且应该自己编写它们:
并添加到令牌过滤器:
cors和过滤器顺序的设置: