簡體   English   中英

如何在 Spring Boot 中將 GenericFilterBean 數據傳遞給 WebSecurityConfigurerAdapter?

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

我正在嘗試使用以下命令在我的 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); 但這仍然沒有改變任何事情。

這是解決此問題的解決方案。 經查,由於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() 。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM