【问题标题】:grails - spring-security-core secure-channel causing redirect loop (on Heroku)grails - spring-security-core 安全通道导致重定向循环(在 Heroku 上)
【发布时间】:2012-02-01 04:15:19
【问题描述】:

我正在使用 spring-security-core 并设置了安全通道功能,这些功能在我的开发机器上运行良好。我在 Config.groovy 中有以下内容

grails.plugins.springsecurity.secureChannel.definition = [
   '/order/checkout': 'REQUIRES_SECURE_CHANNEL',
   '/order/paymentComplete': 'REQUIRES_INSECURE_CHANNEL'
]

此外,将相关的订单处理部署到 Heroku 可以正常工作,只要我注释掉以上几行。一旦我把它们放回去,我就会得到:

我看到服务器上有很多请求,Firebug 网络视图显示:

我已将 PiggyBack SSL 添加到 Heroku,并且可以指定 https://... 地址以导航到站点的其他部分,在这种情况下,浏览器将保持 SSL 模式。但是如果我访问

https:/www.momentumnow.co/order/checkout 

address 直接,我得到相同的重定向循环问题。你知道问题是什么或者我可以如何进一步调试。如果是后者,请您更新评论区,我会回复问题区的更新。谢谢

PiggyBack SSL documentation 表示:

“Piggyback SSL 将允许您使用 https://yourapp.heroku.com,因为它使用 *.heroku.com 认证。您无需购买或配置证书,它就可以工作。https://yourcustomdomain.com 可以工作,但它将在浏览器中产生警告。”

我可能会在添加证书时切换到另一种模式,但是根据前面的说法,这似乎不是问题。


在服务器上,我得到:

【问题讨论】:

标签: grails


【解决方案1】:

您需要修复端口的值,因为它们默认为 8080 和 8443。请参阅文档中的通道安全部分 - http://grails-plugins.github.com/grails-spring-security-core/docs/manual/ - 关于 grails.plugins.springsecurity.portMapper.httpPortgrails.plugins.springsecurity.portMapper.httpsPort 配置属性。

【讨论】:

  • 啊——太棒了。感谢指出一般问题(以及向我展示在哪里可以找到答案)。非常感激。另外,你能告诉我是否应该继续退出 spring-security-UI(并添加我自己的注册码)以在 Heroku 上工作? (这是 spring-security-ui 使用的插件明显与 Heroku 插件不兼容的问题)。谢谢。
  • 嗯。在 Heroku 中搜索 SSL 端口信息,但没有找到,因此我使用 80 作为 httpPort,使用 443 作为 httpsPort。仍然得到同样的错误(除了我在请求中看到端口 443)。另外,当我只是做site时,我可以看到来回发送的数据包中的远程端口是443,所以这似乎是正确的端口。
【解决方案2】:

对于遇到此问题的其他人(就像我一样),问题是您的应用实际上并未以 HTTPS 形式接收请求。相反,Heroku 将 HTTPS 替换为“X-Forwarded-Proto”标头。然后 Spring-security 的 HTTPS 重定向会将您置于无限重定向循环中,因为它总是将请求检测为 HTTP。

你可以自己写SecureChannelProcessor来处理这个问题:

public class HerokuSecureChannelProcessor extends SecureChannelProcessor {

    @Override
    public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config)
            throws IOException, ServletException {
        Assert.isTrue((invocation != null) && (config != null),
                "Nulls cannot be provided");

        for (ConfigAttribute attribute : config) {
            if (supports(attribute)) {
                String header = invocation.getHttpRequest().getHeader("X-Forwarded-Proto");
                if(header == null){
                    // proceed normally
                    if (!invocation.getHttpRequest().isSecure()) {
                        getEntryPoint().commence(invocation.getRequest(), invocation.getResponse());
                    }
                } else {
                    // use heroku header instead
                    if("http".equals(header)) {
                        getEntryPoint().commence(invocation.getRequest(), invocation.getResponse());
                    }
                }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 2015-01-12
    相关资源
    最近更新 更多