public class TokenFilter implements Filter {
public static final String HEADER_AUTH_NAME = "Authorization";
@Autowired
JWTProvider jwtProvider;
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
String authToken = httpServletRequest.getHeader(HEADER_AUTH_NAME);
if (StringUtils.isNotBlank(authToken)) {
// 从自定义tokenProvider中解析用户
Authentication authentication = this.jwtProvider.getAuthentication(authToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
// 调用后续的Filter,如果上面的代码逻辑未能复原“session”,SecurityContext中没有想过信息,后面的流程会检测出"需要登录"
chain.doFilter(req, res);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
当我们直接或间接的继承了Filter之后,Spring Security 会自动将过滤器添加多执行列表中。
如果我们仍将其添加到 WebSecurityConfigurerAdapter 中
@Configuration
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
private LoginAuthenticationFilter loginAuthenticationFilter;
@Autowired
private TokenFilter tokenFilter;
@Autowired
private CorsConfigurationSource configurationSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(loginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
// .addFilterBefore(tokenFilter,UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests()
.antMatchers("/login","/register").permitAll()
.anyRequest().authenticated()
.and()
.cors().configurationSource(configurationSource)
// 关闭 csrf 保护
.and()
.csrf().disable()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
// 返回 json 格式的数据
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
Map<String, Object> map = new HashMap<>(16);
map.put("status:", 200);
map.put("msg:","注销登录成功!");
writer.write(new ObjectMapper().writeValueAsString(map));
writer.flush();
writer.close();
}
});
}
@Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
}
就会对此过滤词执行两次。