如何在Spring Boot中将GenericFilterBean数据传递到WebSecurityConfigurerAdapter?

发布于 2021-02-02 11:36:47

我正在尝试使用以下命令在我的Spring Boot应用程序中将http重定向到https:

http.requiresChannel().anyRequest().requiresSecure();

但是我越来越ERR_TOO_MANY_REDIRECTS。原因是负载均衡器将所有https都转换为http并将http定向到端口8082,因此该应用似乎从未看到过https。

我尝试通过在http到https重定向之前添加isSecure来解决此问题,例如在我的配置中:

public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
        //variables
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/css/**", "/js/**", "/admin/**")
                .permitAll().anyRequest().authenticated().and()
                .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class)
                .formLogin().loginPage("/login").permitAll().and()
                .logout().logoutSuccessUrl("/");

        //hsts
        http.headers().httpStrictTransportSecurity()
        .includeSubDomains(true).maxAgeInSeconds(31536000);

        http.addFilterBefore(new IsSecureFilter(), ChannelProcessingFilter.class);

        //https compulsion
        if(!isSecureFilter.isSecure()) {
                http.requiresChannel().anyRequest().requiresSecure();
        }           
    }
       //rest of the code
}

我尝试使用HttpServletRequestWrapper,以便可以通过下面创建的IsSecureFilter在WebSecurityConfiguration中重复使用isSecure,以防止无限重定向:

public class RequestWrapper extends HttpServletRequestWrapper {
    private boolean isSecure;

    public RequestWrapper(HttpServletRequest request) throws IOException
    {
        //So that other request method behave just like before
        super(request);
        this.isSecure = request.isSecure();       
    }

    //Use this method to read the request isSecure N times
    public boolean isSecure() {
        return this.isSecure;
    }  
}

下面是我尝试在WebSecurityConfiguration中注入的过滤器,以使用上面的isSecure值:

@Component
public class IsSecureFilter extends GenericFilterBean {

    private boolean isSecure;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = new RequestWrapper((HttpServletRequest) request);

        this.isSecure = req.isSecure();

        chain.doFilter(req, response);
    }

    public boolean isSecure() {
        return this.isSecure;
    }
}

所以运行上面的代码并放入example.com/login浏览器确实重定向到了https://example.com/login,但是我仍然可以ERR_TOO_MANY_REDIRECTS。我不明白我在做什么错?我的第一个想法是:

  • 我可以在WebSecurityConfiguration中注入IsSecureFilter来检索isSecure吗?

  • 我是否以正确的方式将IsSecureFilter筛选器添加到配置中。

  • 包装过滤器关系是否正确定义?

编辑

1) 我更改http.addFilterAfter(new isSecureFilter(), ChannelProcessingFilter.class);http.addFilterAfter(isSecureFilter, ChannelProcessingFilter.class);,仍然没有效果。

2) 我尝试更改http.addFilterBefore(isSecureFilter, ChannelProcessingFilter.class);为,http.addFilterAfter(isSecureFilter, ChannelProcessingFilter.class);但仍然没有任何更改。

关注者
0
被浏览
84
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    这是解决此问题的解决方案。根据调查,由于8080和8082用于识别HTTP通信和HTTPS通信,因此添加了一些代码来检查端口号,而不是“
    isSecure”,以确定是否重定向HTTP请求。代码如下:

    public class IsSecureFilter extends GenericFilterBean {
    
    private boolean isSecure;
    private int port;
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = new RequestWrapper((HttpServletRequest) request);
        HttpServletResponse res = (HttpServletResponse) response;
        this.isSecure = req.isSecure();
        this.port = req.getLocalPort();
    
    
        System.out.println("[DEBUG] : isSecure FILTER :: " + isSecure);
        System.out.println("[DEBUG] : port FILTER :: " + port);
        System.out.println("[DEBUG] : URL :: " + req.getRequestURL());
        String url = req.getRequestURL().toString().toLowerCase();
        if(url.endsWith("/login") && url.startsWith("http:") && port == 8080){
            url = url.replace("http:", "https:");
            String queries = req.getQueryString();
            if (queries == null) {
                queries = "";
            } else {
                queries = "?" + queries;
            }
            url += queries;
            res.sendRedirect(url);
        }
        else {
            chain.doFilter(req, response);
        }
    }
    
    public boolean isSecure() {
        return this.isSecure;
    }
    
    public boolean setIsSecure(boolean isSecure) {
        return this.isSecure = isSecure;
    }
    
    public int getPort() {
        return port;
    }
    
    public void setPort(int port) {
        this.port = port;
    }
    

    }

    并在WebSecurityConfiguration类中删除http.requiresChannel()。anyRequest()。requiresSecure()。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看