我正在尝试为Web应用程序上的某些页面启用HTTPS。我使用Spring MVC和Spring Security作为部署在Tomcat上的Web应用程序,使用Nginx作为tomcat的代理。
首先,没有任何HTTPS配置,一切正常。我生成了一个自签名的SSL证书并将其安装在Nginx上。我没有对Tomcat进行任何更改以启用HTTPS,因为我只想让Nginx处理SSL终止。这是我对SSL的相关Nginx配置。
listen 443;
server_name 127.0.0.1;
root /usr/local/server/web/webapps/ROOT;
ssl on;
ssl_certificate /usr/local/etc/nginx/ssl/server.crt;
ssl_certificate_key /usr/local/etc/nginx/ssl/server.key;
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
我的SSL Spring安全配置如下所示:
<http pattern="/static/**" security="none" />
<http pattern="/favicon*" security="none" />
<http use-expressions="true">
<intercept-url pattern="/login" access="permitAll" requires-channel="https" />
<intercept-url pattern="/loginprocess" method="POST" requires-channel="https" />
<intercept-url pattern="/logout" access="isAuthenticated()"/>
<intercept-url pattern="/**" access="isAuthenticated()" requires-channel="https" />
<form-login username-parameter="username"
password-parameter="password" login-page="/login"
login-processing-url="/loginprocess" default-target-url="/hiring"
authentication-failure-url="/login?error" always-use-default-target="true" />
<logout logout-url="/logout" logout-success-url="/login?logout" />
</http>
现在,当我尝试访问浏览器上的登录页面时https://localhost/internal/login
,我收到错误消息 -
此网页有重定向循环
Spring Security中的日志如下所示:
12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.security.web.FilterChainProxy - /login at position 1 of 10 in additional filter chain; firing Filter: 'ChannelProcessingFilter'
12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/login'; against '/login'
12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.s.w.a.c.ChannelProcessingFilter - Request: FilterInvocation: URL: /login; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.s.w.a.c.RetryWithHttpsEntryPoint - Redirecting to: https://localhost/internal/login
12:34:55.241 [http-bio-8080-exec-33] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to 'https://localhost/internal/login'
我曾尝试过使用require-channel一段时间,但实际上并没有成功。任何帮助/指针都会很棒。
我尝试使用以下配置,重定向循环错误不再存在。但是,使用这些日志进行身份验证失败 -
03:29:28.603 [http-bio-8080-exec-19] DEBUG o.s.s.w.a.c.ChannelProcessingFilter - Request: FilterInvocation: URL: /loginprocess; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
03:29:28.603 [http-bio-8080-exec-19] DEBUG o.s.s.w.a.c.RetryWithHttpsEntryPoint - Redirecting to: https://localhost/internal/loginprocess
03:29:28.603 [http-bio-8080-exec-19] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to 'https://localhost/internal/loginprocess'
03:29:28.609 [http-bio-8080-exec-11] DEBUG o.s.s.web.util.AntPathRequestMatcher - Request 'GET /loginprocess' doesn't match 'POST /loginprocess
03:29:28.609 [http-bio-8080-exec-11] DEBUG o.s.s.web.util.AntPathRequestMatcher - Request '/loginprocess' matched by universal pattern '/**'
03:29:28.614 [http-bio-8080-exec-20] DEBUG o.s.security.web.FilterChainProxy - /loginprocess at position 4 of 10 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
03:29:28.614 [http-bio-8080-exec-20] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Request is to process authentication
03:29:28.615 [http-bio-8080-exec-20] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: Authentication method not supported: GET
我想知道这是否是同样的问题,因为Spring Security向浏览器发送重定向并且它返回了GET请求。但是如果登录登录页面是HTTPS并且Spring因为RemoteIPValve认为它是安全的,为什么再次出现问题呢?
我没有在RemoteIpValve中添加internalProxies参数,这导致了问题。默认情况下在internalProxies中启用了一些IP地址(在我的例子中,它是)。问题是认证是间歇性的。我为RemoteIpValve启用了日志,并观察到代理IP是IpV6格式,它与internalProxies不匹配,因此没有为该请求启用RemoteIpValve,因此出现问题。我在Mac OS X上注释掉#fe80::1%lo0 localhost
行并且问题已经消失了。
顺便说一下@M中的配置。 Deinum的答案似乎运作良好。
答案 0 :(得分:6)
您的HTTPS连接由NGINX处理。与应用程序的连接是HTTP连接。因此在外面基本上是安全的,内部不安全。
Spring Security使用ServletRequest中的isSecure()
方法确定它是否安全,默认情况下会将协议检查为https。
当您使用tomcat时,您可以配置一个额外的阀门RemoteIpValue 3来影响isSecure()
,getRemoteAddr()
方法(以及其他一些方法)的行为。
<Valve
className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="192\.168\.0\.10|192\.168\.0\.11"
remoteIpHeader="x-forwarded-for"
proxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto"
/>
将上述内容添加到<Host >
元素中(当然您可能需要删除/修改内部代理参数)。
在您的Nginx配置中添加X-Forwarded-proto标头。
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Front-End-Https on;
proxy_set_header Host $http_host;
}
或者只是删除对安全通道的检查并假设一切正常......
链接