0
点赞
收藏
分享

微信扫一扫

Spring Security自定义过滤器多次执行的问题

醉倾城1 2022-05-05 阅读 62
spring
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();
    }
}

就会对此过滤词执行两次。

举报

相关推荐

0 条评论