问题遇到的现象和发生背景
gateway在整合spring security 时,配置了白名单的url还是会被 自定义过滤器拦截(自定义过滤器已经交由security管理)
用代码块功能插入代码,请勿粘贴截图
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebfluxSecurityConfig {
@Bean
PasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
LoginFailureHandler loginFailureHandler;
@Autowired
LoginSuccessHandler loginSuccessHandler;
@Autowired
JwtLogoutSuccessHandler jwtLogoutSuccessHandler;
@Autowired
CaptchaFilter captchaFilter;
@Autowired
JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Autowired
UserDetailServiceImpl userDetailService;
private static final String[] URL_WHITELIST = {
"/login",
"/logout",
"/favicon.ico",
"/captcha",
"/product/upload",
"/img/*",
"/mar/check/showpdf"
};
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {
http.csrf().disable()
.formLogin()
.authenticationSuccessHandler(loginSuccessHandler)
.authenticationFailureHandler(loginFailureHandler)
.and()
.logout()
.logoutSuccessHandler(jwtLogoutSuccessHandler)
// 异常处理器
.and()
.exceptionHandling()
.authenticationEntryPoint( jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)
// 配置自定义的过滤器
.and()
.addFilterAfter(new TestFilter(),SecurityWebFiltersOrder.FIRST)
// 配置拦截规则
.authorizeExchange()
.pathMatchers(HttpMethod.GET, URL_WHITELIST).permitAll()
.anyExchange().authenticated()
.and()
.httpBasic().and()
.addFilterAt(new JwtAuthenticationFilter(new JwtUtils(),userDetailService),SecurityWebFiltersOrder.HTTP_BASIC)
.addFilterBefore(captchaFilter, SecurityWebFiltersOrder.HTTP_HEADERS_WRITER);
// 禁用session
return http.build();
}
@Bean
public ReactiveAuthenticationManager reactiveAuthenticationManager(ReactiveUserDetailsService userDetailsService,PasswordEncoder passwordEncoder){
UserDetailsRepositoryReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
return authenticationManager;
}
public class JwtAuthenticationFilter implements WebFilter {
JwtUtils jwtUtils;
UserDetailServiceImpl userDetailService;
public JwtAuthenticationFilter(JwtUtils jwtUtils, UserDetailServiceImpl userDetailService) {
this.jwtUtils = jwtUtils;
this.userDetailService = userDetailService;
}
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
ServerHttpRequest request = serverWebExchange.getRequest();
String jwt = null;
try{
jwt= request.getHeaders().getFirst(jwtUtils.getHeader());
}catch (Exception e){
webFilterChain.filter(serverWebExchange);
}
if (StrUtil.isBlankOrUndefined(jwt)) {
webFilterChain.filter(serverWebExchange);
}
Claims claim = jwtUtils.getClaimByToken(jwt);
if (claim == null) {
throw new JwtException("token为空");
}
if (jwtUtils.isTokenExpired(claim)) {
throw new JwtException("token已过期");
}
String username = claim.getSubject();
// 获取用户的权限等信息
//SysUser sysUser = sysUserService.getByUsername(username);
UsernamePasswordAuthenticationToken token
= new UsernamePasswordAuthenticationToken(username, null, userDetailService.getUserAuthority(new Long(11111)));
SecurityContextHolder.getContext().setAuthentication(token);
return webFilterChain.filter(serverWebExchange);
}
}
运行结果及报错内容
即使是白名单请求也会经过 自定义的 filter