grails - spring-security-core安全通道导致重定向循环(在Heroku上)

时间:2012-02-01 04:15:20

标签: grails

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

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

此外,部署到Heroku时,关联的订单处理工作正常,一样长,因为我注释掉了上面的行。我把它们放回去后,我得到:

redirect error

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

redirect network view

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

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

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

PiggyBack SSL documentation表示:

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

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


在服务器上,我得到:

enter image description here

2 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:1)

对于任何绊到这里的人(就像我一样),问题是你的应用实际上并没有收到HTTPS的请求。而是,Heroku用“X-Forwarded-Proto”标头替换HTTPS。 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());
                    }
                }
            }
        }
    }
}