使用 Spring Security 的 HTTPS 登录重定向到 HTTP

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10385977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:06:22  来源:igfitidea点击:

HTTPS login with Spring Security redirects to HTTP

springsslhttpsspring-securitytomcat6

提问by Thody

I have a Spring web app, secured with Spring Security, running on EC2. In front of the EC2 instance is an Elastic Load Balancer with an SSL cert (https terminates at the load balancer ie. port 443 -> port 80), so from Tomcat's perspective, inbound requests are HTTP.

我有一个 Spring Web 应用程序,受 Spring Security 保护,在 EC2 上运行。EC2 实例前面是一个带有 SSL 证书的弹性负载均衡器(https 终止于负载均衡器,即端口 443 -> 端口 80),因此从 Tomcat 的角度来看,入站请求是 HTTP。

My login form submits to https, however the subsequent redirect goes to http (success or fail). The authentication was successful, and I can go back to https and I'm logged in.

我的登录表单提交到 https,但随后的重定向转到 http(成功或失败)。身份验证成功,我可以回到https并登录。

My login configuration looks like so:

我的登录配置如下所示:

<security:form-login
    default-target-url="/home"
    login-page="/"
    login-processing-url="/processlogin"
    authentication-failure-url="/?login_error=1"/>

What do I need to change to make default-target-url and authentication-failure-url go to https?

我需要更改什么才能使 default-target-url 和 authentication-failure-url 转到 https?

  • Tomcat 6
  • Spring Security 3.0.x
  • 雄猫6
  • 春季安全 3.0.x

回答by marcelj

Your spring configuration should be agnostic to the used protocol. If you use something like "requires-channel", you'll run into problems sooner or later, especially if you want to deploy the same application to a development environment without https.

您的 spring 配置应该与使用的协议无关。如果您使用诸如“requires-channel”之类的东西,您迟早会遇到问题,尤其是如果您想将相同的应用程序部署到没有 https 的开发环境时。

Instead, consider to configure your tomcat properly. You can do this with RemoteIpValve. Depending on which headers the loadbalancer sends, your server.xml configuration needs to contain something like this:

相反,请考虑正确配置您的 tomcat。您可以使用RemoteIpValve做到这一点。根据负载均衡器发送的标头,您的 server.xml 配置需要包含如下内容:

<Valve
   className="org.apache.catalina.valves.RemoteIpValve"
   internalProxies=".*"
   protocolHeader="X-Forwarded-Proto"
   httpsServerPort="443"
   />

Spring will determine the absolute redirect address based on the ServletRequest, so change the httpsServerPort if you are using something else than 443:

Spring 将根据 ServletRequest 确定绝对重定向地址,因此如果您使用的是 443 以外的其他内容,请更改 httpsServerPort:

The httpsServerPort is the port returned by ServletRequest.getServerPort() when the protocolHeader indicates https protocol

httpsServerPort为protocolHeader指示https协议时ServletRequest.getServerPort()返回的端口

回答by Rolch2015

If it is a Spring Boot application (I use currently the 2.0.0 release), the following configuration within the application.propertiesfile should be enough:

如果是 Spring Boot 应用程序(我目前使用的是 2.0.0 版本),application.properties文件中的以下配置应该足够了:

server.tomcat.protocol-header=x-forwarded-proto

This worked for me on AWS with an load balancer at the front.

这在 AWS 上对我有用,前面有一个负载均衡器。

For Spring Boot < 2.0.0 it should also work (not tested)

对于 Spring Boot < 2.0.0 它也应该工作(未测试)

回答by Vlad Saveluc

I had the same problem with Spring Boot behind Google Kubernetes. Adding these two lines to application.properties did it for me

我在使用 Google Kubernetes 后面的 Spring Boot 时遇到了同样的问题。将这两行添加到 application.properties 为我做了

server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto

Source: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-security.html#howto-enable-https

来源:https: //docs.spring.io/spring-boot/docs/current/reference/html/howto-security.html#howto-enable-https

回答by Suresh

One way I got this working is by adding the following config

我让这个工作的一种方法是添加以下配置

<http auto-config="true" use-expressions="true" entry-point-ref="authenticationEntryPoint" >
    <form-login login-page="/login.jsf" authentication-failure-url="/login.jsf?login_error=t" always-use-default-target="true" default-target-url="xxxxx" />
    <logout logout-url="/logout" logout-success-url="/logoutSuccess.jsf" />
    ...
</http>

Had to add always-use-default-target="true"and default-target-url="https://....". Not the ideal way as you need to hard code the url in the config.

必须添加always-use-default-target="true"default-target-url="https://...."。不是理想的方式,因为您需要在配置中对 url 进行硬编码。

回答by Andrew Westberg

I set requires-channel="any" on all intercept-urls. This allows it to still work in my dev environment where I don't use SSL.

我在所有拦截网址上设置了 requires-channel="any"。这使它在我不使用 SSL 的开发环境中仍然可以工作。

<intercept-url pattern="/createUser" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" requires-channel="any"/>
<intercept-url pattern="/**" access="isAuthenticated()" requires-channel="any"/>

Then, create an apache virtual host that redirects all traffic to the HTTPS version.

然后,创建一个 apache 虚拟主机,将所有流量重定向到 HTTPS 版本。

<VirtualHost *:80>
  ServerName www.mywebsite.com
  Redirect permanent / https://www.mywebsite.com/
</VirtualHost>

回答by Agry

I am also facing exactly same problem and till the time I get proper solution I am redirecting my requests from proxy server to tomcat server over AJP instead of HTTP. Below is my apache configuration

我也面临着完全相同的问题,直到我得到正确的解决方案时,我才通过 AJP 而不是 HTTP 将我的请求从代理服务器重定向到 tomcat 服务器。下面是我的apache配置

ProxyPass /myproject ajp://localhost:8009/myproject
ProxyPassReverse /myproject ajp://localhost:8009/myproject

回答by mirzaei

use below lines of code in web.xml

在 web.xml 中使用以下代码行

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Login and Restricted Space URLs</web-resource-name>
    <url-pattern>/j_security_check</url-pattern>
    <url-pattern>/loginpage.rose</url-pattern>
  </web-resource-collection>
  <user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  </user-data-constraint>
</security-constraint>

it makes forced to use HTTPS.

它被迫使用HTTPS。

回答by CelinHC

In my case, I had to REMOVE the property server.use-forward-headers=true.

就我而言,我不得不 REMOVE 属性server.use-forward-headers=true

This is my setup:

这是我的设置:

Digital Ocean LB --> Kubernetes cluster with Ingress --> Spring boot Application

Digital Ocean LB --> 带有 Ingress 的 Kubernetes 集群 --> Spring Boot 应用程序

回答by Mihkel L.

Solution was two fold

解决方案是双重的

(1) application.yml

(1) 应用程序.yml

server:
  use-forward-headers: true

(2) in servers /etc/apache2/sites-enabled/oow.com-le-ssl.conf

(2) 在服务器中 /etc/apache2/sites-enabled/oow.com-le-ssl.conf

RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443

(2.1) and enabled the apache module with

(2.1) 并启用 apache 模块

sudo a2enmod headers

Put it together with the help of thisand this

这个这个的帮助下把它放在一起