我有两个Jetty AppServers在Apache 2.2反向代理后面运行Grails Web App。 SSL终止由apach完成,他们将HTTP传递给Jetty AppServers。
当Grails Web应用程序执行如此重定向时
redirect(action:'index')
最终用户收到带有完整网址的HTTP 302重定向请求,该网址使用的是 http:// 协议,而不是 https:// :
HTTP/1.1 302 Found
Date: Tue, 08 Mar 2011 17:50:46 GMT
Server: Jetty(6.1.17)
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Location: http://hostname.domain/web/?lang=en
这很烦人,因为所有HTTP请求都被代理捕获并重定向到HTTPS请求。所以这是一次不必要的往返。
我看到两个解决方案:
Location: /web/?lang=en
我认为第一个选择有点愚蠢,对吧?
您是否知道我如何能够发送grails来发送非绝对重定向标头(理想情况下无需切换每个重定向以使用uri:
)?
编辑目前我通过修改响应标头(a2enmod headers
)在第一种方法之后找到解决方法,然后在Header edit Location ^http://(.*)$ https://$1
中添加<Location>
。灵感来自this serverfault post。我仍然想知道为什么这首先是必要的。
答案 0 :(得分:6)
302 redirects are required by the HTTP 1.1 RFC to be absolute,而不是相对位置。即使它在某些浏览器中有效,但这些都超出了规范,我确信如果你做了一个相对网址,某些实现将无法正常工作。
您遇到此问题的原因是因为SSL终止发生在apache上,而apache正在向Jetty发出一个vanilla HTTP请求。所以Jetty正在获得一个非常的非HTTPS请求,所以它不知道发送HTTPS响应,而不是常规的HTTP响应。如果您在Jetty中进行SSL终止,则不会出现问题(但Jetty在SSL终止时效果不佳)。
我们已经在我们的应用程序(apache / HA Proxy-&gt; Tomcat)中处理了这个问题,因为它具有硬编码响应协议的每个环境配置值(无论如何我们都需要弄乱网址,因为它是一个多租户系统有许多潜在的主机名,长篇故事...... :),但你的apache解决方案也适用。
答案 1 :(得分:0)
这个问题已经有将近 10 年的历史了。从那时起,规范已在 RFC 7231, section 7.1.2 中更新。现在允许 Location 标头中的相对引用:
<块引用>当 [Location] 具有 相对引用([RFC3986], Section 4.2)的形式,最终 值是通过根据有效的请求 URI 解析它来计算的 ([RFC3986], Section 5)。
Grails 支持这种类型的重定向,但您在重定向时必须应用额外的 absolute: false
参数:
redirect action: 'index', absolute: false
注意:在撰写本文时,此功能(尚)不支持 servlet 上下文路径,请参阅 grails-core issue #11673