本文介绍了Grails:Spring Security CAS在2.2.3中工作,但不在2.3.0中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Groovy 2.0在Grails 2.2.3中有一个项目。我已经与Spring Security建立了使用CAS进行认证和LDAP用于用户角色的设置。当我运行应用程序时,一切正常,因为它应该:任何人都可以访问/ appcontext /,并且/ appcontext / admin /中的任何内容都可以通过CAS和来自LDAP的管理员角色进行保护。我正在尝试使用最新版本的Grails和Groovy。我安装了GGTS 3.4.0.RELEASE,并使用Grails 2.3.0和Groovy 2.1。我创建了一个新项目,创建了一个简单的域类和控制器,并添加到安全设置中。

以GGTS 3.3运行应用程序时,这是我的输出。 0.RELEASE,使用Grails 2.2.3和Groovy 2.0:(注意Server Running消息的位置)

  |加载Grails 2.2.3 
|配置类路径。
|环境设置为开发.....
|打包Grails应用程序.....
|运行Grails应用程序

配置Spring Security Core ...
...完成配置Spring Security Core

配置Spring Security CAS ...
。 ..完成配置Spring Security CAS

配置Spring Security LDAP ...
...完成配置Spring Security LDAP

|服务器运行。浏览到http:// localhost:8080 / appcontext

运行应用程序与GGTS 3.4.0.RELEASE,使用Grails 2.3.0和Groovy 2.1(注意服务器正在运行消息的位置):

  |加载Grails 2.3.0 
|配置类路径。
|环境设置为开发.....
|打包Grails应用程序.....
|编译1个源文件.....
|运行Grails应用程序
|服务器运行。浏览到http:// localhost:8080 / appcontext
配置Spring Security Core ...
...完成配置Spring Security Core
配置Spring Security LDAP ...
。 ..完成配置Spring Security LDAP
初始化应用程序时出错:未定义名为'casAuthenticationProvider'的bean
org.springframework.beans.factory.NoSuchBeanDefinitionException:没有名为'casAuthenticationProvider'的bean被定义
(SpringSecurityCoreGrailsPlugin.groovy:686)
at SpringSecurityCoreGrailsPlugin.createBeanList(SpringSecurityCoreGrailsPlugin.groovy:686)SpringSecurityCoreGrailsPlugin
(SpringSecurityCoreGrailsPlugin.groovy:615)
at at SpringSecurityCoreGrailsPlugin $ _createBeanList_closure22.doCall(SpringSecurityCoreGrailsPlugin.groovy:686) java.util.concurrent.FutureTask $ Sync.innerRun(FutureTask.java:303)$ java.util.concurrent.FutureTask.run上的$ b $(FutureTask.java:138)$ java.util.concurrent中的
。 ThreadPoolExec utor $ Worker.runTask(ThreadPoolExecutor.java:886)$ b $在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:908)$ b $在java.lang.Thread.run(线程。 java:662)
|错误2013-10-15 11:33:02,925 [localhost-startStop-1] ERROR context.GrailsContextLoader - 初始化应用程序时出错:未定义名为'casAuthenticationProvider'的bean
消息:没有定义名为'casAuthenticationProvider'的bean
Line |方法
- >> 686 | doCall SpringSecurityCoreGrailsPlugin $ _createBeanList_closure22
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $ - $ - $ - 615 | SpringSecurityCoreGrailsPlugin中的doCall $ _closure4
| 303 | innerRun。 。 。在java.util.concurrent.FutureTask $ Sync
|中138 |在java.util.concurrent.FutureTask
|运行886 | runTask。 。 。在java.util.concurrent.ThreadPoolExecutor $ Worker
|中908 |运行''
^ 662 |跑 。 。 。 。 。在java.lang.Thread中
模式导出不成功
org.h2.jdbc.JdbcSQLException:数据库已关闭(要禁止在虚拟机关闭时自动关闭,请向db URL添加; DB_CLOSE_ON_EXIT = FALSE) [90121-170]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
at org.h2.message.DbException.get(DbException.java:169)
在org.h2.message.DbException.get(DbException.java:146)
在org.h2.message.DbException.get(DbException.java:135)
在org.h2.jdbc。在org.h2.jdbc.JdbcConnection.getAutoCommit(JdbcConnection.java:JdbcConnection.java: 424)
在java.lang.Thread.run(Thread.java:662)
|错误2013-10-15 11:33:03,071 [线程-9]错误hbm2ddl.SchemaExport - 模式导出不成功
消息:数据库已关闭(要禁用虚拟机关闭时的自动关闭,请添加; DB_CLOSE_ON_EXIT = FALSE到数据库URL)[90121-170]
Line |方法
- >> 329 | getJdbcSQLException in org.h2.message.DbException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 169 |进入''
| 146 |得到。 。 。 。 。 。 。 。在''
|中135 |进入''
| 1391 | checkClosed。 。 。 。在org.h2.jdbc.JdbcConnection
|中1366 |在''
| checkClosed中424 | getAutoCommit。 。 。 in''
^ 662 |在java.lang.Thread
|运行错误分叉Grails虚拟机退出,出现错误

以下是我的基本安全设置:



> conf / spring / resources.groovy

  import org.apache .commons.lang.StringEscapeUtils 

//将您的Spring DSL代码放在这里
beans = {
//从spring security安装ldap角色
def ldapUrl = StringEscapeUtils。 escapeJava('$ {ldap.defaultUrl}')
def ldapUser = StringEscapeUtils.escapeJava('$ {ldap.username'')
def ldapPassword = StringEscapeUtils.escapeJava('$ {ldap.password}' )
def ldapBase = StringEscapeUtils.escapeJava('$ {ldap.base}')
def ldapRoleSearchBase = StringEscapeUtils.escapeJava('$ {ldap.roleSearchBase}')

initialDirContextFactory (org.springframework.security.ldap.DefaultSpringSecurityContextSource,ldapUrl){
userDn = ldapUser
password = ldapPassword
}

ldapUserSearch(org.spring framework.security.ldap.search.FilterBasedLdapUserSearch,
ldapBase,'sAccountName = {0}',initialDirContextFactory){}

ldapAuthoritiesPopulator(org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator,
initialDirContextFactory,ldapRoleSearchBase){
groupRoleAttribute ='cn'
groupSearchFilter ='member = {0}'
searchSubtree = true
rolePrefix ='ROLE_'
convertToUpperCase = true
ignorePartialResultException = true
}

userDetailsS​​ervice(org.springframework.security.ldap.userdetails.LdapUserDetailsS​​ervice,ldapUserSearch,ldapAuthoritiesPopulator){}

}

conf / Config.groovy

  def appName = grails.util.Metadata.current.getApplicationName()

environments {
开发{
gr ails.logging.jul.usebridge = true

host.ip =12.34.56.78
host.port =8080
host.securePort =8080
ldap.username =ldapUsername
ldap.password =ldapPassword
ldap.base =DC = foo,DC = company,DC = com
ldap.roleSearchBase = OU = bar,DC = foo,DC = company,DC = com
ldap.defaultUrl =ldap://123.45.67.89:389
ldap.urls =ldap://123.45。 67.89:389 ldap://123.45.67.89:389

cas.url =https://sso.company.com/cas/
cas.loginUrl =https:
cas.logoutUrl =https://sso.company.com/cas/logout

grails.plugins.springsecurity.cas .serviceUrl ='http:// $ {host.ip}:$ {host.securePort} /'+ appName +'/ j_spring_cas_security_check'
grails.plugins.springsecurity.cas.proxyCallbackUrl ='http:// $ {host.ip}:$ {host.securePort} /'+ appName +'/ secure / receptor'
}
pr oduction {
grails.logging.jul.usebridge = false
grails.plugins.springsecurity.cas.serviceUrl ='https:// $ {host.ip}:$ {host.securePort} /'+ appName +'/ j_spring_cas_security_check'
grails.plugins.springsecurity.cas.proxyCallbackUrl ='https:// $ {host.ip}:$ {host.securePort} /'+ appName +'/ secure / receptor'



// spring安全核心配置
grails.plugins.springsecurity.providerNames = ['casAuthenticationProvider']
grails.plugins.springsecurity。 rejectIfNoRule = true
grails.plugins.springsecurity.securityConfigType =InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = [
'/ js / **':['IS_AUTHENTICATED_ANONYMOUSLY'],
'/ css / **':['IS_AUTHENTICATED_ANONYMOUSLY'],
'/ images / **':['IS_AUTHENTICATED_ANONYMOUSLY'],
'/ admin / login / **':[ 'IS_AUTHENTICATED_ANONYMOUSLY'],
'/ admin / logout / **':['IS_AUTHENTICATED_A NONYMOUSLY'],
'/ admin / **':['hasAnyRole(ROLE_ADMIN)'],
'/ **':['IS_AUTHENTICATED_ANONYMOUSLY']
]

// cas配置
grails.plugins.springsecurity.cas.loginUri ='login'
grails.plugins.springsecurity.cas.serverUrlPrefix ='$ {cas.url}'
grails.plugins.springsecurity.cas.proxyReceptorUrl ='/ secure / receptor'

conf / BuildConfig.groovy

  compile:spring-security-core:1.2.7.3
编译:spring-security-cas:1.0.5
compile:spring-security-ldap:1.0.6

编辑
使用下面接受的答案的建议,我能够正确配置Spring Security CAS,但是我的控制器仍然不安全。我认为它必须处理应用服务器说它正在运行的奇怪加载顺序,然后加载Spring Security,LDAP和CAS。一位同事建议取出我的InterceptUrlMap并使用@Secured注释来查看它是否是加载顺序(因为InterceptUrlMap在所有事情都已启动并运行后无法更新)。我摆脱了rejectIfNoRule,securityConfigType和interceptUrlMap设置,并向控制器添加了@Secured(['ROLE_ADMIN'])。该应用程序现在可以按预期工作,并且控制器是安全的。



因此,Grails 2.3.0和Spring Security的事件顺序仍然存在问题,但是这个是一种解决方法。



相关问题:

解决方案

我看到同样的事情。看起来CAS插件默认来自在Grails 2.3.0下未正确合并。可能值得一个JIRA。与此同时,您可以通过将默认设置添加到Config.groovy(覆盖您的环境)来向前迈进:

  grails.plugins.springsecurity.cas.active = true 
grails.plugins.springsecurity.cas.loginUri = null //必须设置,例如'/ login'
grails.plugins.springsecurity.cas.sendRenew = false
grails.plugins.springsecurity.cas.serviceUrl = null //必须设置,例如'http:// localhost:8080 / myapp / j_spring_cas_security_check'
必须设置grails.plugins.springsecurity.cas.serverUrlPrefix = null // 'http:// localhost:9090 / cas'
grails.plugins.springsecurity.cas.serverUrlEncoding ='UTF-8'
grails.plugins.springsecurity.cas.key ='grails-spring-security -cas'
grails.plugins.springsecurity.cas.artifactParameter ='ticket'
grails.plugins.springsecurity.cas.serviceParameter ='service'
grails.plugins.springsecurity.cas.filterProcessesUrl ='/ j_spring_cas_security_check'
grails.plugins.springsecurity.cas.proxyCallbackUrl = null //应设置,例如'http:// localhost:8080 / myapp / secure / receptor'
应该设置grails.plugins.springsecurity.cas.proxyReceptorUrl = null //。 '/ secure / receptor'
grails.plugins.springsecurity.cas.useSingleSignout = true


I have a project in Grails 2.2.3 using Groovy 2.0. I have it set up with Spring Security to use CAS for authentication and LDAP for user roles. When I run the app, everything works as it should: accessing /appcontext/ is allowed by anyone and anything under /appcontext/admin/ is secured by CAS and an admin role from LDAP. I am trying to use the newest versions of Grails and Groovy now. I installed GGTS 3.4.0.RELEASE and am using Grails 2.3.0 and Groovy 2.1. I created a new project, made a simple domain class and controller and added in the security settings.

Here is my output when running the app with GGTS 3.3.0.RELEASE, using Grails 2.2.3 and Groovy 2.0: (note the location of the "Server Running" message)

| Loading Grails 2.2.3
| Configuring classpath.
| Environment set to development.....
| Packaging Grails application.....
| Running Grails application

Configuring Spring Security Core ...
... finished configuring Spring Security Core

Configuring Spring Security CAS ...
... finished configuring Spring Security CAS

Configuring Spring Security LDAP ...
... finished configuring Spring Security LDAP

| Server running. Browse to http://localhost:8080/appcontext

Here is my output when running the app with GGTS 3.4.0.RELEASE, using Grails 2.3.0 and Groovy 2.1 (note the location of the "Server Running" message):

| Loading Grails 2.3.0
| Configuring classpath.
| Environment set to development.....
| Packaging Grails application.....
| Compiling 1 source files.....
| Running Grails application
| Server running. Browse to http://localhost:8080/appcontext
Configuring Spring Security Core ...
... finished configuring Spring Security Core
Configuring Spring Security LDAP ...
... finished configuring Spring Security LDAP
Error initializing the application: No bean named 'casAuthenticationProvider' is defined
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'casAuthenticationProvider' is defined
        at SpringSecurityCoreGrailsPlugin$_createBeanList_closure22.doCall(SpringSecurityCoreGrailsPlugin.groovy:686)
        at SpringSecurityCoreGrailsPlugin.createBeanList(SpringSecurityCoreGrailsPlugin.groovy:686)
        at SpringSecurityCoreGrailsPlugin$_closure4.doCall(SpringSecurityCoreGrailsPlugin.groovy:615)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
| Error 2013-10-15 11:33:02,925 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: No bean named 'casAuthenticationProvider' is defined
Message: No bean named 'casAuthenticationProvider' is defined
   Line | Method
->> 686 | doCall         in SpringSecurityCoreGrailsPlugin$_createBeanList_closure22
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   615 | doCall         in SpringSecurityCoreGrailsPlugin$_closure4
|   303 | innerRun . . . in java.util.concurrent.FutureTask$Sync
|   138 | run            in java.util.concurrent.FutureTask
|   886 | runTask . . .  in java.util.concurrent.ThreadPoolExecutor$Worker
|   908 | run            in     ''
^   662 | run . . . . .  in java.lang.Thread
schema export unsuccessful
org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing     at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-170]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
    at org.h2.message.DbException.get(DbException.java:169)
    at org.h2.message.DbException.get(DbException.java:146)
    at org.h2.message.DbException.get(DbException.java:135)
    at org.h2.jdbc.JdbcConnection.checkClosed(JdbcConnection.java:1391)
    at org.h2.jdbc.JdbcConnection.checkClosed(JdbcConnection.java:1366)
    at org.h2.jdbc.JdbcConnection.getAutoCommit(JdbcConnection.java:424)
    at java.lang.Thread.run(Thread.java:662)
| Error 2013-10-15 11:33:03,071 [Thread-9] ERROR hbm2ddl.SchemaExport  - schema export unsuccessful
Message: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-170]
    Line | Method
->>  329 | getJdbcSQLException in org.h2.message.DbException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|    169 | get                 in     ''
|    146 | get . . . . . . . . in     ''
|    135 | get                 in     ''
|   1391 | checkClosed . . . . in org.h2.jdbc.JdbcConnection
|   1366 | checkClosed         in     ''
|    424 | getAutoCommit . . . in     ''
^    662 | run                 in java.lang.Thread
| Error Forked Grails VM exited with error

Here is my basic security setup:

conf/spring/resources.groovy

import org.apache.commons.lang.StringEscapeUtils

// Place your Spring DSL code here
beans = {
    // load ldap roles from spring security
    def ldapUrl = StringEscapeUtils.escapeJava('${ldap.defaultUrl}')
    def ldapUser = StringEscapeUtils.escapeJava('${ldap.username}')
    def ldapPassword = StringEscapeUtils.escapeJava('${ldap.password}')
    def ldapBase = StringEscapeUtils.escapeJava('${ldap.base}')
    def ldapRoleSearchBase = StringEscapeUtils.escapeJava('${ldap.roleSearchBase}')

    initialDirContextFactory(org.springframework.security.ldap.DefaultSpringSecurityContextSource, ldapUrl){
        userDn = ldapUser
        password = ldapPassword
    }

    ldapUserSearch(org.springframework.security.ldap.search.FilterBasedLdapUserSearch,
        ldapBase, 'sAMAccountName={0}', initialDirContextFactory){ }

    ldapAuthoritiesPopulator(org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator,
        initialDirContextFactory, ldapRoleSearchBase){
            groupRoleAttribute = 'cn'
            groupSearchFilter = 'member={0}'
            searchSubtree = true
            rolePrefix = 'ROLE_'
            convertToUpperCase = true
            ignorePartialResultException = true
        }

    userDetailsService(org.springframework.security.ldap.userdetails.LdapUserDetailsService,ldapUserSearch,ldapAuthoritiesPopulator){ }

}

conf/Config.groovy

def appName = grails.util.Metadata.current.getApplicationName()

environments {
    development {
        grails.logging.jul.usebridge = true

        host.ip = "12.34.56.78"
        host.port = "8080"
        host.securePort = "8080"
        ldap.username = "ldapUsername"
        ldap.password = "ldapPassword"
        ldap.base = "DC=foo,DC=company,DC=com"
        ldap.roleSearchBase = "OU=bar,DC=foo,DC=company,DC=com"
        ldap.defaultUrl = "ldap://123.45.67.89:389"
        ldap.urls = "ldap://123.45.67.89:389 ldap://123.45.67.89:389"

        cas.url = "https://sso.company.com/cas/"
        cas.loginUrl = "https://sso.company.com/cas/login"
        cas.logoutUrl = "https://sso.company.com/cas/logout"

        grails.plugins.springsecurity.cas.serviceUrl = 'http://${host.ip}:${host.securePort}/' + appName +'/j_spring_cas_security_check'
        grails.plugins.springsecurity.cas.proxyCallbackUrl = 'http://${host.ip}:${host.securePort}/' + appName +'/secure/receptor'
    }
    production {
        grails.logging.jul.usebridge = false
        grails.plugins.springsecurity.cas.serviceUrl = 'https://${host.ip}:${host.securePort}/' + appName +'/j_spring_cas_security_check'
        grails.plugins.springsecurity.cas.proxyCallbackUrl = 'https://${host.ip}:${host.securePort}/' + appName +'/secure/receptor'
    }
}

//spring security core config
grails.plugins.springsecurity.providerNames = ['casAuthenticationProvider']
grails.plugins.springsecurity.rejectIfNoRule = true
grails.plugins.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugins.springsecurity.interceptUrlMap = [
    '/js/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
    '/css/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
    '/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
    '/admin/login/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
    '/admin/logout/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
    '/admin/**': ['hasAnyRole("ROLE_ADMIN")'],
    '/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
]

//cas config
grails.plugins.springsecurity.cas.loginUri = 'login'
grails.plugins.springsecurity.cas.serverUrlPrefix = '${cas.url}'
grails.plugins.springsecurity.cas.proxyReceptorUrl = '/secure/receptor'

conf/BuildConfig.groovy

compile ":spring-security-core:1.2.7.3"
compile ":spring-security-cas:1.0.5"
compile ":spring-security-ldap:1.0.6"

EDITUsing the advice of the accepted answer below, I was able to get Spring Security CAS to configure correctly, but my controllers were still unsecured. I figured that it had to do with that weird load order where the app server says it's running and THEN it loads Spring Security, LDAP, and CAS. A coworker suggested taking out my InterceptUrlMap and using @Secured annotations to see if it was the loading order (since InterceptUrlMap can't be updated after everything is up and running). I got rid of the rejectIfNoRule, securityConfigType, and interceptUrlMap settings and added a @Secured(['ROLE_ADMIN']) to the controller. The app now works as expected and that controller is secured.

So, there is still an issue with the order of events with Grails 2.3.0 and Spring Security, but this is a workaround.

Related question: https://stackoverflow.com/questions/19411102/grails-2-3-0-spring-security-ldap-and-cas-load-after-server-starts

解决方案

I see the same thing. Looks like the CAS plugin defaults from DefaultCasSecurityConfig.groovy are not merged properly under Grails 2.3.0. Possibly worth a JIRA. In the meantime, you may be able to move forward by adding the defaults to Config.groovy (overriding for your environment):

grails.plugins.springsecurity.cas.active = true
grails.plugins.springsecurity.cas.loginUri = null // must be set, e.g. '/login'
grails.plugins.springsecurity.cas.sendRenew = false
grails.plugins.springsecurity.cas.serviceUrl = null // must be set, e.g. 'http://localhost:8080/myapp/j_spring_cas_security_check'
grails.plugins.springsecurity.cas.serverUrlPrefix = null // must be set, e.g. 'http://localhost:9090/cas'
grails.plugins.springsecurity.cas.serverUrlEncoding = 'UTF-8'
grails.plugins.springsecurity.cas.key = 'grails-spring-security-cas'
grails.plugins.springsecurity.cas.artifactParameter = 'ticket'
grails.plugins.springsecurity.cas.serviceParameter = 'service'
grails.plugins.springsecurity.cas.filterProcessesUrl = '/j_spring_cas_security_check'
grails.plugins.springsecurity.cas.proxyCallbackUrl = null // should be set, e.g. 'http://localhost:8080/myapp/secure/receptor'
grails.plugins.springsecurity.cas.proxyReceptorUrl = null // should be set, e.g. '/secure/receptor'
grails.plugins.springsecurity.cas.useSingleSignout = true

这篇关于Grails:Spring Security CAS在2.2.3中工作,但不在2.3.0中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 20:13