2

Because setting the ports in this question didn't solve the redirect loop problem, I created a bare-bones test app (grails 2.0, latest spring-security-core 1.2.7.1), so the redirect loop problem is easy to reproduce / hopefully solve: Here are the steps:

1- Created new app called test, and created a controller called simple (also in a test package), i.e.:

   package test

   class SimpleController {
       def index()  { redirect action: 'start'    }
       def start()  { render "start - not secure" }
       def middle() { render "middle - secure"    }
       def end()    { render "end - not secure"   }
   }  

2- Did grails install spring-security-core and also grails s2-quickstart test User Role

3- In Config.groovy, added following lines, and then did run-app -https to test on my dev machine:

   grails.plugins.springsecurity.secureChannel.definition = [
     '/simple/middle/**':    'REQUIRES_SECURE_CHANNEL',
     '/simple/end/**':       'REQUIRES_INSECURE_CHANNEL',
     '/simple/**':           'ANY_CHANNEL'
   ]

RESULT: all checks out, can enter URLs ../simple/start, and then entering ../simple/middle enters SSL/https mode, as desired.

4- In Config.groovy, I then configured ports to run on Heroku (guestimate, found no docs/refs):

  grails.plugins.springsecurity.portMapper.httpPort = '80'
  grails.plugins.springsecurity.portMapper.httpsPort = '443'

5- After doing the steps git init, git add ., git commit -m "initial commit", and heroku create --stack cedar , I went to Heroku and added the PiggyBack SSL to the newly created app there. I then did a git push heroku master to deploy.

RESULT: Got common "IllegalStateException, no thread-bound request found", a problem described here and here.

6- As such, in BuildConfig.groovy, I made the following 2 changes to the plugins {} section:

    //runtime ":resources:1.1.5"
    compile ":webxml:1.4.1"   

RESULT: IllegalStateException goes away, and I'm able to access the simple controller (and login controller). I'm able to prefix those urls with https, and all is good. However, if I enter the ../simple/middle URL, I get the redirect loop (traces similar to here).

7- Out of curiosity I commented out half the change in step 6, namely //compile: "webxml:1.4.1":

RESULT: got same IllegalStateException

8- Because I wasn't sure how the heroku and cloud support plugins factored into the basic steps steps above, I waited to add them in until this step. I then did grails install-plugin cloud-support and grails install-plugin heroku, and updated BuildConfig.groovy so it now looks like:

   plugins {
     runtime ":hibernate:$grailsVersion"
     runtime ":jquery:1.7.1"

      //runtime ":resources:1.1.5"
      //compile ":webxml:1.4.1"
      compile ':heroku:1.0'
      compile ':cloud-support:1.0.8'

      compile ":tomcat:$grailsVersion"
   }

and then did a clean and updated the git repository and pushed out to heroku.

RESULT: same IllegalStateException (note the webxml dependency is commented out).

9- I then uncommented compile ":webxml:1.4.1", and pushed out to heroku again:

RESULT: exactly as in step 3. I.e. with the exception of ../simple/middle, all URLs work, including adding an https prefix. Goiing to the ../simple/middle URL causes the redirect loop problem.

Can you please advise how to solve this? If there are things for me to try out (i.e. non-definite solution), please just update the comments section and I'll respond back with results. Thanks much.

------------------------------------------------------------------------------------------

Update using new spring-security 1.2.7.2.

My BuildConfig.groovy is now:

 dependencies {
    // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
    runtime 'mysql:mysql-connector-java:5.1.16'
}

plugins {
    runtime ":hibernate:$grailsVersion"
    runtime ":jquery:1.7.1"

    runtime ":resources:1.1.6"
    compile ":spring-security-core:1.2.7.2"

    compile ":webxml:1.4.1"

    compile ':heroku:1.0'
    compile ':cloud-support:1.0.8'

    build ":tomcat:$grailsVersion"
}

Got a PostGres dependency error deploying to Heroku even though using MySql. So I removed all apps on Heroku and blew away my git repository, and started with a fresh deployment/fresh app.

Still get this PostGres dependency error (below). Note: got the "No Transaction manager found - if you webapp requires one, please configure one" warning previously when the MySql worked. Hmm.

  12-02-03T07:18:09+00:00 app[web.1]: 2012-02-03 07:18:09.810:INFO:omjr.Runner:Runner
  12-02-03T07:18:09+00:00 app[web.1]: 2012-02-03 07:18:09.811:WARN:omjr.Runner:No tx manager found
  12-02-03T07:18:09+00:00 app[web.1]: 2012-02-03 07:18:09.852:INFO:omjr.Runner:Deploying  file:/app/target/momentum-0.1.war @ /
  12-02-03T07:18:09+00:00 app[web.1]: 2012-02-03 07:18:09.869:INFO:oejs.Server:jetty-7.x.y-SNAPSHOT
 12-02-03T07:18:09+00:00 app[web.1]: [o.e.j.w.WebAppContext{/,null},file:/app/target/momentum-0.1.war]
 12-02-03T07:18:09+00:00 app[web.1]: 2012-02-03  07:18:09.915:INFO:oejw.WebInfConfiguration:Extract jar:file:/app/target/momentum-0.1.war!/ to   /tmp/jetty-0.0.0.0-43683-momentum-0.1.war-_-any-/webapp
 12-02-03T07:18:14+00:00 app[web.1]: 2012-02-03 07:18:14.500:INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one.
 12-02-03T07:18:18+00:00 app[web.1]: 2012-02-03 07:18:18.361:INFO:/:Initializing Spring root WebApplicationContext
 12-02-03T07:18:24+00:00 app[web.1]:
 12-02-03T07:18:24+00:00 app[web.1]: Configuring Spring Security Core ...
 12-02-03T07:18:24+00:00 app[web.1]: ... finished configuring Spring Security Core
 12-02-03T07:18:24+00:00 app[web.1]:
 12-02-03T07:18:24+00:00 app[web.1]: 2012-02-03 07:18:24.490:WARN:oejw.WebAppContext:Failed    startup of context o.e.j.w.WebAppContext{/,file:/tmp/jetty-0.0.0.0-43683-momentum-0.1.war-_-any- /webapp/},file:/a
   /target/momentum-0.1.war
   12-02-03T07:18:24+00:00 app[web.1]: org.springframework.beans.factory.BeanCreationException:   Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; 
    ************************************************************   
    nested exception is org.springframework.beans.factory.BeanCreationException: Error  creating bean with name 'sessionFactory': Cannot resolve reference to bean 'lobHandlerDetector' while  setting bean property 'lobHandler'; 
      nested exception is org.springframework.beans.factory.BeanCreationException:  Error creating bean with name 'lobHandlerDetector': Invocation of init method failed; 
   nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class 'org.postgresql.Driver'
   *************************************************************

  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory.doCreateBean(ReloadAwareAutowireCapableBeanFactory.java:126)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:707)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:449)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.codehaus.groovy.grails.commons.spring.DefaultRuntimeSpringConfiguration.getApplicationContext(DefaultRuntimeSpringConfiguration.java:153)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator.configure(GrailsRuntimeConfigurator.java:124)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator.configure(GrailsRuntimeConfigurator.java:165)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.codehaus.groovy.grails.web.context.GrailsConfigUtils.configureWebApplicationContext(GrailsConfigUtils.java:121)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.codehaus.groovy.grails.web.context.GrailsContextLoader.initWebApplicationContext(GrailsContextLoader.java:104)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:643)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:233)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1213)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:589)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:454)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
  12-02-03T07:18:24+00:00 app[web.1]:   at  org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:167)
  12-02-03T07:18:24+00:00 app[web.1]:   at  org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.server.Server.doStart(Server.java:261)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.mortbay.jetty.runner.Runner.run(Runner.java:500)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.mortbay.jetty.runner.Runner.main(Runner.java:639)
  12-02-03T07:18:24+00:00 app[web.1]:   at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224)
Community
  • 1
  • 1
Ray
  • 5,885
  • 16
  • 61
  • 97

1 Answers1

2

Probably best not to just randomly hack out stuff if you don't know why it's there :)

The IllegalStateException is coming from an incorrect ordering of filter-mapping elements in web.xml. Both spring-security-core and resources were positioning filter-mapping elements and were stepping on each other, so we updated the webxml plugin to support that by convention and made both plugins depend on that one. Due to bugs in plugin eviction with different dependent plugin versions, it's important that you use versions of spring-security-core and resources that depend on the same version of webxml.

New 2.0 apps declare a dependency on resources 1.1.5 which uses webxml v1.4, and spring-security-core 1.2.7+ uses 1.4.1, so you need to either not use resources or use version 1.1.6. Then there's no ambiguity and the correct version will be used, and the web.xml order will be correct. You should also register all plugins in BuildConfig and not use install-plugin; this will keep everything in one place and allow you to define exclusions, etc.

This is all independent of the SSL issues however, so it's best to focus on one issue at a time. I haven't used SSL on Heroku so I don't know what ports they use. I assume inside the firewall they use something other than 443 and then requests are routed out on 443. But this is independent of Grails and the spring-security-core plugin, so finding out how SSL is configured is just a general documentation issue.

Update

Ok, so based on the workaround in the link James posted I released a new version of the Spring Security plugin (v1.2.7.2) with support for X-Forwarded-Proto. Add grails.plugins.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true to Config.groovy and it will use that approach instead of the more simplistic secure/insecure check. And the IllegalStateException is due to a bug in the way Heroku deploys Grails 2.0 applications. Plugin dependencies aren't getting resolved when building the war, so you need to be explicit. So be sure to add

compile ":spring-security-core:1.2.7.2"
compile ':webxml:1.4.1'
compile ":heroku:1.0"
compile ':cloud-support:1.0.8'

to BuildConfig.groovy to be sure that webxml (a spring-security-core dependency) and cloud-support (a heroku dependency) get installed and deployed.

Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
  • Heroku terminates the http and https connections at the load balancer and then just talks http back to the dyno. The load balancer sets a request header `x-forwarded-proto` so that the dyno can know if the original request was secure or not. Unfortunately Spring Security doesn't handle this right now. See: http://stackoverflow.com/questions/6732453/spring-security-requires-channel-https-behind-ssl-accelerator – James Ward Feb 02 '12 at 20:39
  • Thanks for your response. Please note I get the IllegalStateException when I (now) use runtime ":resources:1.1.6" and compile ":spring-security-core:1.2.7.1", and no webxml:1.4.1. Also, please note I only added webxml per this blog (http://padcom13.blogspot.com/2011/12/grails-heroku-and-spring-security-core.html), not able to get rid of the IllegalStateException. I don't need it for other use. So, I'm confused: should I be able to get rid of the IllegalStateException, WITHOUT directly declaring a webxml dependency? Using 1.1.6 with 1.2.7.1 alone doesn't work for me. – Ray Feb 02 '12 at 22:51
  • Also, to clarify about the webxml plugin. You need this plugin, but it has to be the right version. If you don't have it the filters won't be in the correct order. Best case is you get an ugly error and are forced to fix it. Worst case is you get subtle issues you don't know about like unguarded resources. – Burt Beckwith Feb 03 '12 at 04:43
  • Thank you, I will try this out. Just a clarification on the resources plugin: should I do "r:resources:1.1.6", 1.1.5, or comment it out? Also, what is the state of using spring-security-ui on Heroku. Is the solution to the plugin collision there still being worked? – Ray Feb 03 '12 at 05:41
  • Either use 1.1.6 or nothing. 1.1.5 will cause problems (IllegalStateException again). Still working on the UI plugin. – Burt Beckwith Feb 03 '12 at 06:47
  • Thanks. I'm trying above and getting a postGres type error, "cannot load JDBC driver class 'pog.postgresql.driver'. Did you by chance hard-wire a dependency to postgres in the update. Worked fine with MySql earlier today (except SSL problem), and it's not running any more. Perhaps something got messed up on Heroku. – Ray Feb 03 '12 at 06:50
  • I blew everything away on Heroku and added the various SSL and Domain Add-ons including MySQL. Am still getting postGres dependency error -- although can't see how, as I don't have it in my grails project. Could something you did change Heroku's req. for postGres? Please note my BuildConfig.groovy above, at the end of the question area under "update". – Ray Feb 03 '12 at 07:24
  • The postgresql issue isn't related to this. I'm not sure what's causing it, but for the short term you can add a dependency for the driver jar (see the tutorials in the docs for the syntax) and raise a JIRA for this problem. – Burt Beckwith Feb 03 '12 at 17:19
  • I added runtime 'postgresql:postgresql:9.0-801.jdbc4' and got even worse problems -- more exceptions than before. Would it be possible for you to test a "commonly deployed project" on Heroku:, i.e. spring-security/SSL and MySql? Otherwise there is so much time spent on trying to reproduce problems and incrementally address fixes. – Ray Feb 03 '12 at 21:35
  • Sure, but let's get this out of this discussion since it's a separate issue. Please create a JIRA issue for the Heroku plugin, or another SO question. – Burt Beckwith Feb 03 '12 at 22:21
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7324/discussion-between-ray-and-burt-beckwith) – Ray Feb 03 '12 at 22:51
  • In process of creating an example MySql project for the JIRA I have run into the other Grails problems. Can you please tell me what you mean by "You should also register all plugins in BuildConfig and not use install-plugin"? I.e. so one should not do an install-plugin spring-security-core (e.g. in order to do the s2-quickstart command)? Seems necessary, so can you please elaborate. – Ray Feb 04 '12 at 00:49
  • Never mind last question, someone pointed out refresh-dependencies command (unfortunately not mentioned in Ch. 3 or in the entire http://grails.org/doc/2.0.x/guide/single.html if one searches on the term). Regarding me writing a JIRA, I guess I could once gain build a trivial example on Heroku with MySql and Spring-security-core and SSL. But if you are doing this as part of the spring-security-ui work and testing, then I would rather not repeat this process, unless it is important for your work flow. If it is, please indicate that here and I will check back and do that process. Thanks. – Ray Feb 04 '12 at 04:12