Grails Spring Security如何使用https重定向到登陆页面

12

我有一个使用Spring Security Core的Grails应用程序,运行在AWS机器后面的一个负载均衡器上。

负载均衡器解密SSL连接,并将请求转发到我们实例的8080端口,并添加适当的X-Forwarded-Proto头。

我希望任何对受保护页面的直接访问都能够使用https重定向到登录页面。

例如,请求https://myapp.com/private/page应该重定向到https://myapp.com/login/auth

我将以下内容放入我的config.groovy文件中:

grails.plugin.springsecurity.secureChannel.definition = [
    '/login/**':        'REQUIRES_SECURE_CHANNEL'
]

但这会导致重定向循环(HTTP代码302)到http登录页面 (http://myapp.com/login/auth)

然后我尝试仅使用:

grails.plugin.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugin.springsecurity.auth.forceHttps = true

但这会导致重定向(HTTP代码302)到http登录页面(http://myapp.com/login/auth

  1. 该问题仅在生产设置中出现(war部署到负载均衡器后的Tomcat)。
  2. 如果我在本地开发机器上测试相同的config.groovy,则重定向到https://myapp.com/login/auth可以正常工作。
  3. 我尝试指定不同的httpsPort用于Spring安全性,同样在我的本地开发机器上有效,但在部署的应用程序中完全被忽略,仍然会重定向到http。

阅读了类似帖子后没有找到解决方法,有任何想法吗?

3个回答

8
我也使用Spring Security Core 2.0-RC4在AWS上托管我的Grails应用程序,并使用https和负载均衡器,感谢spock99(上面)和AWS的Ravi L,我让它工作了。
我在config.groovy中执行以下操作:
    // Required because user auth uses absolute redirects
    grails.serverURL = "http://example.com"

    grails.plugin.springsecurity.secureChannel.definition = [
        '/assets/**':     'ANY_CHANNEL',// make js, css, images available to logged out pages
        '/**':            'REQUIRES_SECURE_CHANNEL',
    ]

    // overriding values in DefaultSecurityConfig.groovy from the SpringSecurityCore 2.0-RC4 
    grails.plugin.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
    grails.plugin.springsecurity.portMapper.httpPort = 80
    grails.plugin.springsecurity.portMapper.httpsPort = 443

注意:以下内容在Spring Security Core 2.0-RC4中不再需要 - 它们已经包含在DefaultSecurityConfig.groovy中了

    secureHeaderName = 'X-Forwarded-Proto'
    secureHeaderValue = 'http'
    insecureHeaderName = 'X-Forwarded-Proto'
    insecureHeaderValue = 'https'

我一直得到错误的“不健康”读数,因为访问'/'会返回302重定向到/login/auth,所以我在HomeController中添加了一个health()方法(将其映射到'/health')供AWS使用:

    class HomeController {
        @Secured('IS_AUTHENTICATED_FULLY')
        def index() { }

        @Secured('permitAll')
        def health() { render '' }
    }

对我来说关键是在负载均衡器上运行多个实例时,会话cookie未被正确处理(直到将最小实例数设置为2才发现此问题),因此为了使用户能够登录并保持登录状态,在AWS上执行以下操作:

1.  At Services / Elastic Beanstalk / Configuration / Load Balancing 
    a. set Application health check URL: /health
    b. left Session Stickiness: unchecked
2. At Services / EC2 / Load Balancers / Description / Port Configuration:
    For both port 80 (HTTP)  and 443 (HTTPS)
        1. Edit and select 'Enable Application Generated Cookie Stickiness'
        2. Cookie Name: JSESSIONID

4

我曾经遇到过同样的情况。第一次遇到了https问题,然后是重定向,但现在一切都好了。使用以下这些 Config.groovy 设置:

grails.plugin.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugin.springsecurity.portMapper.httpPort = 80
grails.plugin.springsecurity.portMapper.httpsPort = 443
grails.plugin.springsecurity.secureChannel.secureHeaderName = 'X-Forwarded-Proto'
grails.plugin.springsecurity.secureChannel.secureHeaderValue = 'http'
grails.plugin.springsecurity.secureChannel.insecureHeaderName = 'X-Forwarded-Proto'
grails.plugin.springsecurity.secureChannel.insecureHeaderValue = 'https'

对于那些没有使用springsecurity 2.0的人来说,它是“plugins”而不是“plugin”没有“s”。
我的beanstalk负载均衡器设置如下所示(我安装了SSL证书,但我没有展示):
在EC2负载均衡器设置中,确保您的侦听器设置正确:
最后,在EC2安全组中,确保EB接受来自ELB的端口80和443的请求:
请注意,在我的任何设置中都没有引用端口8080或8443,即使这是我在本地主机上进行测试时使用的端口。阅读此内容的某些人可能会考虑尝试使用这些端口来解决问题。我的设置不需要这样做。

非常感谢您的帮助,但是没有运气!我复制了相同的设置,也将内部端口移动到80,但它总是重定向到http...您在grails.plugin.springsecurity.secureChannel.definition中有任何内容吗?您有任何想法可以至少调试它吗? - Paull
1
我没有为secureChannel.definition设置值。你的生产环境中是否设置了grails.serverURL?这是另一个导致我的应用程序出现问题的原因,但我认为这与设置cloudfront有关。我没有使用日志进行调试。我会在配置文件中进行更改并上传新的war文件,然后使用浏览器逐步执行每个场景以查看哪些出现了问题。然后我会再次进行更改并重试。 - spock99
你使用的Spring Security版本是什么? - spock99
对于生产环境,我有:grails.serverURL = "https://my.app.com"。我正在使用":spring-security-core:2.0-RC2"。 - Paull
我的服务器网址是http://www.mycompany.com。我不知道http是否会有所不同。我也在使用RC2。你没有使用VPC吧?我曾经在VPC上遇到了很多麻烦,最终不得不将所有的VPC从AWS中移除。在和AWS支持团队商讨了近一个小时之后,我发现这对我的设置来说并非必要。 - spock99
这对我有用,使用负载均衡器在ElasticBeansTalk上部署。 - Neoecos

1
我在类似的环境中遇到了类似的问题,前端使用https,而防火墙后面的grails服务器使用http。当会话超时时,ajax和angular $http会收到一个重定向消息http://myclient.com/myWar/login/auth。此重定向请求会导致浏览器访问被拒绝,因为原始url是https,混合内容被禁用。我曾经收到SCRIPT7002:XMLHttpRequest:网络错误0x80700013,无法完成操作,因为发生了错误80700013。” 这个错误只在生产环境中出现,而不是测试环境中。 解决方法很简单,只需将以下内容添加到配置文件中。 grails.serverURL = "https://mywebsitespublicaddress.com/myWar"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接