我正在尝试为 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'
我尝试使用 requires-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,因此出现了问题。#fe80::1%lo0 localhost
我在我的 Mac OS X 上注释掉了这条线,问题就消失了。
顺便说一下@M中的配置。Deinum 的回答似乎效果很好。