[英]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.