HandlerInterceptorAdapter 在使用 Spring Security 登录时不运行

Posted

技术标签:

【中文标题】HandlerInterceptorAdapter 在使用 Spring Security 登录时不运行【英文标题】:HandlerInterceptorAdapter doesn't run on login with Spring Security 【发布时间】:2017-08-13 04:55:05 【问题描述】:

我的拦截器在所有请求中运行,登录时除外。

拦截器:

public class MultitenantHandler extends HandlerInterceptorAdapter 

        private static final Logger log = LoggerFactory.getLogger(MultitenantHandler.class);

        @Override
        public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler)

            String origin = req.getHeader("Origin");
            log.debug("Origin: "+origin);

            if (origin == null) 
                origin = "localhost";
            

            int indexDot = origin.indexOf(".");
            int indexDash = origin.indexOf("://") + 3;

            String tenant = "";

            if (indexDot == -1) 
                tenant = "experter";
                log.warn("Using default tenant");
                TenantContext.setCurrentTenant(tenant);

             else 
                tenant = origin.substring(indexDash, indexDot);
                log.info("Using tenant: " + tenant);
                TenantContext.setCurrentTenant(tenant);
            

            return true;

        

WebMvcConfigurerAdapter我这样注册:

    @Override
    public void addInterceptors(InterceptorRegistry registry) 
        registry.addInterceptor(new MultitenantHandler());
    

这是我的安全配置:

@Configuration
@EnableWebSecurity
@Profile("development", "demo", "default")
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    private final Logger log = LoggerFactory.getLogger(SecurityConfig.class);

    @Autowired
    private CustomUserDetailsService customUserDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RESTAuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private RESTLogoutSuccessHandler logoutSuccessHandler;

    @Autowired
    private JWTAuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private JWTAuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private StatelessAuthenticationFilter statelessAuthFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception 

        http.csrf().disable()
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);

        http.formLogin().permitAll()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler);

        http.logout().permitAll()
                .logoutSuccessHandler(logoutSuccessHandler);

        http.addFilterBefore(statelessAuthFilter, UsernamePasswordAuthenticationFilter.class);

        http.authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers("/v2/api-docs").hasRole("ADMIN")
                .antMatchers("/login").permitAll()
                .antMatchers("/login/changePassword").permitAll()
                .antMatchers("/user/image").permitAll()
                .antMatchers("/social/login/facebook").permitAll()
                .antMatchers("/actuator/**").hasRole("ADMIN")
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/**").hasRole("USER");

        log.info("Configuration of http complete.");
    

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception 
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder);
    

当我请求/login时拦截器没有运行,在其他请求中甚至没有记录拦截器正常工作。

我需要在任何请求之前执行拦截器,因为我需要根据url请求设置数据库。

如果您需要更多信息,请告诉我,我可以在这里发帖。

【问题讨论】:

Spring Security 是使用过滤器实现的,过滤器在 DispatcherServlet 和您拥有的任何控制器/处理程序之前执行。所以它当然不会运行。使用过滤器而不是 HandlerInterceptor 来实现它。 感谢您的回复@M.Deinum。但是一旦我知道过滤器就不会改变这种方法的行为。根据***.com/a/35856496/2463802“过滤器非常适合请求内容和视图内容处理,例如多部分表单和 GZIP 压缩。这通常表明何时需要将过滤器映射到某些内容类型(例如图像)或所有请求。 " 您对过滤器的理解存在缺陷。您想要实现的目标是使用处理程序拦截器无法实现的,您必须使用过滤器。过滤器可以比Handlerinterceptor 做更多的事情,正如之前提到的,Spring Security 是使用过滤器实现的,因此HandlerInterceptor 根本不是一个选项。 太棒了!我了解工作原理,可以解决我的问题。 【参考方案1】:

如果您有同样的问题,我使用@M.Deinum 建议的过滤器解决了这个问题。我使用了与验证身份验证令牌相同的过滤器。

【讨论】:

以上是关于HandlerInterceptorAdapter 在使用 Spring Security 登录时不运行的主要内容,如果未能解决你的问题,请参考以下文章

我们如何在 HandlerInterceptorAdapter 中 postHandle 异常?

HandlerInterceptorAdapter 在使用 Spring Security 登录时不运行

调用HandlerInterceptorAdapter子类的postHandle方法时,ModelAndView为null

Spring中RequestContextHolder以及HandlerInterceptorAdapter的使用

spring拦截器HandlerInterceptorAdapter,能不能控制范围?

利用spring框架提供的HandlerInterceptorAdapter,实现自定义拦截器