简体   繁体   English

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

[英]How to pass GenericFilterBean data to WebSecurityConfigurerAdapter in Spring Boot?

I am trying to redirect http to https in my spring boot application using:我正在尝试使用以下命令在我的 Spring Boot 应用程序中将 http 重定向到 https:

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

But I am getting ERR_TOO_MANY_REDIRECTS .但我收到ERR_TOO_MANY_REDIRECTS The reason for this is that the load balancer converts all the https to http and directs the http to port 8082, therefore the app never seems to see the https.这样做的原因是负载均衡器将所有 https 转换为 http 并将 http 定向到端口 8082,因此应用程序似乎永远不会看到 https。

I tried to fix this by adding isSecure before the http to https redirection, like this in my configuration:我试图通过在 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
}

I am trying to use HttpServletRequestWrapper so that I can repeatedly use isSecure in WebSecurityConfiguration above through the IsSecureFilter I have created below, to prevent infinite redirects:我正在尝试使用 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;
    }  
}

Below is the filter that I am trying to inject in WebSecurityConfiguration, to use it's isSecure value above :下面是我试图在 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;
    }
}

So running the above code and putting example.com/login in the browser does redirect to https://example.com/login , but i am still getting ERR_TOO_MANY_REDIRECTS .所以运行上面的代码并将example.com/login放在浏览器中确实重定向到https://example.com/login ,但我仍然收到ERR_TOO_MANY_REDIRECTS I can't understand what I am doing wrong?我不明白我做错了什么? My first thoughts are:我的第一个想法是:

  • Can I inject the IsSecureFilter in WebSecurityConfiguration to retrieve isSecure?我可以在 WebSecurityConfiguration 中注入 IsSecureFilter 来检索 isSecure 吗?

  • Am I adding the IsSecureFilter filter in a correct way to the configuration.我是否以正确的方式将 IsSecureFilter 过滤器添加到配置中。

  • Is the wrapper filter relationship defined correctly?是否正确定义了包装过滤器关系?

EDIT编辑

1) I changed http.addFilterAfter(new isSecureFilter(), ChannelProcessingFilter.class); 1)我改变了http.addFilterAfter(new isSecureFilter(), ChannelProcessingFilter.class); to http.addFilterAfter(isSecureFilter, ChannelProcessingFilter.class);http.addFilterAfter(isSecureFilter, ChannelProcessingFilter.class); , still no effect. ,还是没有效果。

2) I tried changing http.addFilterBefore(isSecureFilter, ChannelProcessingFilter.class); 2)我尝试更改http.addFilterBefore(isSecureFilter, ChannelProcessingFilter.class); to http.addFilterAfter(isSecureFilter, ChannelProcessingFilter.class);http.addFilterAfter(isSecureFilter, ChannelProcessingFilter.class); but that still did not change anything.但这仍然没有改变任何事情。

Here is the solution to resolve this issue.这是解决此问题的解决方案。 Based on investigation, since 8080 and 8082 are used to identify HTTP traffic and HTTPS traffic, some code are added to check the port number instead "isSecure" to decide whether redirect HTTP request or not.经查,由于8080和8082用于识别HTTP流量和HTTPS流量,所以增加了一些代码来检查端口号而不是“isSecure”来决定是否重定向HTTP请求。 The code is like following:代码如下:

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;
}

} }

and remove http.requiresChannel().anyRequest().requiresSecure() in WebSecurityConfiguration class.并删除 WebSecurityConfiguration 类中的 http.requiresChannel().anyRequest().requiresSecure() 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 仅在Spring Boot 2.0.0响应时执行GenericFilterBean - Execute GenericFilterBean only on response with Spring boot 2.0.0 如何在 Spring Boot 2.7 中使用 userDetailsService 更新已弃用的 WebSecurityConfigurerAdapter - How to update deprecated WebSecurityConfigurerAdapter with userDetailsService in Spring Boot 2.7 Spring Boot permitAll 在 WebSecurityConfigurerAdapter 中不起作用 - Spring Boot permitAll not working in WebSecurityConfigurerAdapter 在 Spring Boot 中为 ResourceServerConfigurerAdapter 替换 WebSecurityConfigurerAdapter - Replace WebSecurityConfigurerAdapter in Spring boot for ResourceServerConfigurerAdapter 如何修复升级到Spring Boot 3.0.0时WebSecurityConfigurerAdapter报错? - How to fix error of WebSecurityConfigurerAdapter when upgrade to Spring Boot 3.0.0? spring-boot 中有多个 WebSecurityConfigurerAdapter 的问题 - Issue with having multiple WebSecurityConfigurerAdapter in spring-boot 用于CSRF的Spring Boot Security XML与WebSecurityConfigurerAdapter - Spring Boot Security XML vs WebSecurityConfigurerAdapter for CSRF Spring 引导中的多个 WebSecurityConfigurerAdapter 不能一起工作 - Multiple WebSecurityConfigurerAdapter in Spring Boot not working together Spring boot 2.x 中的身份验证处理与 WebSecurityConfigurerAdapter - Authentication handling in Spring boot 2.x with WebSecurityConfigurerAdapter Spring Boot 中的多个 WebSecurityConfigurerAdapter 用于多种模式 - Multiple WebSecurityConfigurerAdapter in spring boot for multiple patterns
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM