问题
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)
回答1:
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.
来源:https://stackoverflow.com/questions/9105084/grails-simple-app-to-test-spring-security-core-secure-channel-on-heroku