2

Groovy 2.0 を使用する Grails 2.2.3 のプロジェクトがあります。認証にCASを使用し、ユーザーロールにLDAPを使用するように、Spring Securityでセットアップしました。アプリを実行すると、すべてが正常に機能します。/appcontext/ へのアクセスは誰でも許可され、/appcontext/admin/ の下にあるものはすべて CAS と LDAP の管理者ロールによって保護されます。現在、Grails と Groovy の最新バージョンを使用しようとしています。GGTS 3.4.0.RELEASE をインストールし、Grails 2.3.0 と Groovy 2.1 を使用しています。新しいプロジェクトを作成し、単純なドメイン クラスとコントローラーを作成し、セキュリティ設定に追加しました。

Grails 2.2.3 と Groovy 2.0 を使用して、GGTS 3.3.0.RELEASE でアプリを実行したときの出力を次に示します (「Server Running」メッセージの場所に注意してください)。

| 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

Grails 2.3.0 と Groovy 2.1 を使用して、GGTS 3.4.0.RELEASE でアプリを実行したときの出力を次に示します (「Server Running」メッセージの場所に注意してください)。

| 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

これが私の基本的なセキュリティ設定です。

conf/春/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"

EDIT 以下の受け入れられた回答のアドバイスを使用して、Spring Security CAS を正しく構成することができましたが、コントローラーはまだ保護されていませんでした。アプリサーバーが実行中であると言い、Spring Security、LDAP、およびCASをロードするという奇妙なロード順序に関係していると私は考えました。同僚は、私の InterceptUrlMap を取り出して @Secured アノテーションを使用して、それが読み込み順序であるかどうかを確認することを提案しました (InterceptUrlMap はすべてが稼働した後に更新できないため)。rejectIfNoRule、securityConfigType、interceptUrlMap の設定を取り除き、コントローラーに @Secured(['ROLE_ADMIN']) を追加しました。アプリは期待どおりに動作し、コントローラーは保護されています。

そのため、Grails 2.3.0 と Spring Security のイベントの順序にはまだ問題がありますが、これは回避策です。

関連する質問: https://stackoverflow.com/questions/19411102/grails-2-3-0-spring-security-ldap-and-cas-load-after-server-starts

4

2 に答える 2

3

私は同じことを見ます。DefaultCasSecurityConfig.groovyの CAS プラグインのデフォルトが、Grails 2.3.0 で適切にマージされていないようです。おそらくJIRAの価値があります。それまでの間、デフォルトを Config.groovy に追加することで先に進むことができる場合があります (環境のオーバーライド)。

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
于 2013-10-16T00:08:56.267 に答える
0

このスレッドが少し古いことは知っていますが、2.0-RC1 で同じ問題が発生したときに偶然見つけました。

私が見つけたのは、デフォルトの構成が SpringSecurityCasGrailsPlugin.groovy にロードされていないことでした。これは、かなり前に修正された Tomcat に .War ファイルをデプロイするときに発生した問題でした。その修正のために追加されたコードは、実行が許可されていれば、この新しい問題を修正しました。以下に示すように、条件が常に true になるように単純に強制しましたif(コードは SpringSecurityCasGrailsPlugin.groovy の 105 行目あたりからのものです)。

if (true /*application.warDeployed*/) {
    // need to load secondary here since web.xml was already built, so
    // doWithWebDescriptor isn't called when deployed as war

    SpringSecurityUtils.loadSecondaryConfig 'DefaultCasSecurityConfig'
    conf = SpringSecurityUtils.securityConfig
}

(if ステートメントのみが変更され、残りのコードは説明用です)。

これがどのような副作用を引き起こす可能性があるかはわかりません(まだわかりません...)。run-app コマンドに違いがあり、.war デプロイメントなどのように動作するようです。とにかく、私は確かにこの方法で本番アプリを展開することを躊躇し、受け入れられた回答のようにすべての構成オプションを手動で作成することを選択します. しかし、おそらくこれは、本当の問題を理解できる人に洞察を与えるでしょう.

于 2014-04-10T00:43:39.667 に答える