Grails:Spring Security CAS 在 2.2.3 中工作但不在 2.3.0 中 [英] Grails: Spring Security CAS working in 2.2.3 but not in 2.3.0

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

问题描述

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

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.

这是我使用 GGTS 3.3.0.RELEASE 运行应用程序时的输出,使用 Grails 2.2.3 和 Groovy 2.0:(注意服务器运行"消息的位置)

| 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

这是我使用 GGTS 3.4.0.RELEASE 运行应用程序时的输出,使用 Grails 2.3.0 和 Groovy 2.1(注意服务器运行"消息的位置):

| 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"

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

EDIT Using 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.

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

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

相关问题:https://stackoverflow.com/questions/19411102/grails-2-3-0-spring-security-ldap-and-cas-load-after-server-starts

推荐答案

我看到了同样的事情.看起来 CAS 插件默认来自 DefaultCasSecurityConfig.groovy 在 Grails 2.3.0 下没有正确合并.可能值得一个 JIRA.同时,您可以通过将默认值添加到 Config.groovy(覆盖您的环境)来继续前进:

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 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆