Grails Spring Security 使用 https 重定向到登录页面

Posted

技术标签:

【中文标题】Grails Spring Security 使用 https 重定向到登录页面【英文标题】:Grails Spring Security redirect to login page using https 【发布时间】:2014-01-01 14:03:30 【问题描述】:

我有一个使用 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)

    问题仅存在于生产设置(战争部署到负载平衡器后面的 Tomcat)。 如果我在本地开发机器上测试相同的 config.groovy,重定向到 https://myapp.com/login/auth 就可以了。 我尝试为 spring 安全性指定不同的 httpsPort,它再次在我的本地开发机器上工作,但在不断重定向到 http 的已部署应用程序中被完全忽略

没有运气潜伏在类似的帖子,知道吗?

【问题讨论】:

【参考方案1】:

我还在 AWS 上使用带有 https 和负载均衡器的 Spring Security Core 2.0-RC4 托管我的 Grails 应用程序,感谢 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

【讨论】:

【参考方案2】:

我刚刚经历了同样的场景。卡在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 中有什么吗?关于如何至少调试它的任何想法? 我没有为secureChannel.definition 设置值。您是否为生产环境设置了 grails.serverURL?那是破坏我的应用程序的另一件事,但我认为这与设置云端有关。我没有用日志调试它。我会在配置文件中进行更改并上传新的战争,然后使用浏览器逐步完成每个场景以查看发生了什么问题。然后我会做出改变,然后再试一次。 你用的是什么版本的spring security? 对于生产我有:grails.serverURL = "my.app.com"。我正在使用“:spring-security-core:2.0-RC2” 我的服务器网址是 http://www.mycompany.com。我不知道http是否会有所作为。我也在使用RC2。您没有使用 VPC 是吗?我在使用 VPC 时遇到了很多麻烦,最终将所有 VPC 从 AWS 中剥离出来。在与 AWS 支持协商了近一个小时后,我的设置没有必要。【参考方案3】:

我在类似的环境中遇到了类似的问题,其中前端在 https 上,而防火墙 grails 服务器在 http 上。 当会话超时时,ajax 和 angular $http 用于获取重定向消息到http://myclient.com/myWar/login/auth。此重定向请求用于导致浏览器中的访问被拒绝,因为原始 url 是 https 并且混合内容被禁用。 我曾经得到 SCRIPT7002: XMLHttpRequest: Network Error 0x80700013, 由于错误 80700013 无法完成操作。” 此错误仅发生在生产环境中,而不发生在测试环境中。

修复很简单,只需将以下内容添加到配置文件中即可。 grails.serverURL = "https://mywebsitespublicaddress.com/myWar"

【讨论】:

以上是关于Grails Spring Security 使用 https 重定向到登录页面的主要内容,如果未能解决你的问题,请参考以下文章

Grails - grails-spring-security-rest - 无法从 application.yml 加载 jwt 机密

使用 Spring Security Grails 插件编码密码

Grails + spring-security-core:用户登录后如何分配角色?

在 Grails 中使用 Pre/Post Spring-Security Annotations

Grails 3.0 和 Spring Security

Grails - 卸载 Spring Security Core