2

I have deployed a very simple Grails test app on Cloud Foundry which uses spring-security for the login page.

I want to require HTTPS access for this login page so that passwords are not sent in clear text.

First thing I did was to browse to my test app using HTTPS which worked fine, so that confirmed that Cloud Foundry can service HTTPS requests for my app.

Next I added the following to Config.groovy to require HTTPS access to my pages:

grails.plugins.springsecurity.auth.forceHttps = true

grails.plugins.springsecurity.secureChannel.definition = [
        '/': 'REQUIRES_SECURE_CHANNEL'
]

Now when I try to deploy using grails cf-update it hangs when Trying to start application...

If if I remove the requirement for HTTPS it succeeds.

I'm guessing that maybe there is a problem with the check for whether the application has started. Is this using a HTTP url which is then getting redirected to HTTPS as I cannot see any problems in the logs?

Any ideas?

4

2 回答 2

1

I found out that there currently is an issue with CloudFoundry + Spring Security where HttpServletRequest.isSecure() does not return the correct value when using https. This trumps Spring Security in doing an infinite redirect loop when requiring a secure channel.

I witnessed that on a plain Spring project, but this may be what your grails project is suffering from. One workaround at the moment would be to wrap your HttpServletRequests so that isSecure() looks at the scheme to decide what to return.

If you try your secured URL in a browser, what do you get (assuming the app has actually started, although the grails plugin tells otherwise)

于 2012-09-26T15:54:32.847 回答
0

The problem is that cloudfoundry terminates HTTPS at the loadbalancer. And there is no way to get HTTPS all the way to your app, so 'REQUIRES_SECURE_CHANNEL' will not work on cloudfoundry.

If you want a gross hack to try to check that HTTPS was used between the user and the loadbalancer you can look at the headers in a filter. Eg.

    sslHeaderRequireFilter(controller:'*', action:'*') {
        before = {
            def headerNames = request.headerNames.collect{ it }             
            if(! headerNames.contains('sslclientcertstatus') ){
                render "Only available on https"
                return false    
            }                   
        }
    }
于 2012-09-27T21:46:10.520 回答