apache - 部署在代理后面时,Grails 会生成正确的链接

标签 apache tomcat grails https

考虑以下已部署的 Grails 应用程序的设置。

  • Grails 应用程序部署在 Tomcat 服务器 (tomcat7) 上
  • 在 Tomcat 前面部署了一个 Apache 网络服务器
  • Apache 执行 SSL 卸载,并充当 Tomcat 的代理

到目前为止,这是一个非常标准的设置,我已经成功使用了很多次。我现在的问题是 Grails 应用程序生成的链接,尤其是那些用于重定向的链接(标准 Controller 重定向,它一直发生,例如在成功发布表单之后)。

到目前为止,有一个配置不同于所有其他应用程序:在此 Grails 应用程序中,没有配置 serverURL。该应用程序是一个 Multi-Tenancy 应用程序,其中每个租户都有自己的子域。 (因此,如果应用程序通常在 https://www.example.com 下运行,则租户可以使用 https://tenant.example.com。)子域是自动设置的,即在 DNS 或 Apache 级别没有任何配置。 Grails 可以完美地做到这一点,方法是在 Config.groovy 中省略 serverURL 属性:然后它通过检查客户端主机来解析所有 url。

但是:在生成重定向 URL 时,Grails 并不知道该网站是在 https 下运行的。所有重定向 url 都以 http 开头...我想这并不奇怪,因为在应用程序中没有配置我们使用 https:没有 serverURL 配置,从技术上讲,应用程序正在上运行Tomcat 的标准 http 端口,因为 Apache 的 SSL 卸载和代理。

那么,归根结底:我该怎么做才能使 Grails 生成正确的重定向?

我已尝试扩展 DefaultLinkGenerator 并覆盖 makeServerURL() 方法。像这样:

class MyLinkGenerator extends DefaultLinkGenerator {

MyLinkGenerator(String serverBaseURL, String contextPath) {
    super(serverBaseURL, contextPath)
}

MyLinkGenerator(String serverBaseURL) {
    super(serverBaseURL)
}

def grailsApplication

/**
 * @return serverURL adapted to deployed scheme
 */
String makeServerURL() {
    // get configured protocol
    def scheme = grailsApplication.config.grails.twt.baseProtocol ?: 'https://'
    println "Application running under protocol $scheme"

    // get url from super
    String surl = super.makeServerURL()
    println "> super.makeServerURL(): $surl"
    if (surl) {
        // if super url not matching scheme, change scheme
        if (scheme=='https://' && surl?.startsWith('http://')) {
            surl = scheme + surl?.substring(7)
            println "> re-written: $surl"
        }
    }

    return surl

}

}

(可能不是最漂亮的代码,但我希望它能解释我想做的事情。我在 resources.groovy 中省略了关于配置此类的内容。)

当运行这段代码时,奇怪的事情发生了:

  • 在日志中,您看到正在执行的代码,并生成了更改后的 url (http > https),​​但是...
  • 发送到浏览器的重定向是不变的 url (http)
  • 更糟糕的是:生成的 View 中的所有资源都被削弱了:它们现在都以//开头(所以应该是相对的“/css/myapp.css”现在是“//css/myapp.css” )

如有任何帮助或见解,我们将不胜感激!

顺便说一下,Grails 版本是 2.1.1(升级有点落后......)。

最佳答案

您似乎总是在与外界进行 https 通信,因此您最干净的选择是在您的 Apache 网络服务器上解决问题的源头。添加到 httpd.conf Header edit Location ^http://(.*)$ https://$1,就大功告成了。

如果您有限制迫使您在应用程序中解决这个问题,您可以在拦截器之后重写 Grails 中的 Location header 字段。该解决方案的详细信息在 this post 中.

关于apache - 部署在代理后面时,Grails 会生成正确的链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29693237/

相关文章:

java - apache 守护程序 procrun- java 应用程序作为 windows 服务- 无法在 64 位 windows 7 中启动

linux - 需要 shell 脚本,当检测到我的 5 个重写规则文件中的任何更改/修改时,将执行/etc/init.d/httpd

ruby-on-rails - jruby on rails with warbler 和 tomcat 以及 windows

tomcat - 如何在 Tomcat-OpenEJB 中部署 EJB 2.0、JAR 和 EAR?

hibernate - 扩展域类导致奇怪的表布局和不可访问的字段

php - 我如何在命令行上运行 curl?

windows - 什么是最简单的 Tomcat/Apache 连接器 (Windows)?

java.lang.ClassCircularityError : java/util/logging/LogRecord from Tomcat8 错误

grails - 空指针异常和空对象

sql-server - 如何使用 Grails 将数据从 SQL Server 同步到 Oracle