1

私は Grails 2.4.4 を使用しており、Spring Security Core 2.0-RC4、機能的な Spock 0.7 を備えた Spring Security REST 1.5.0.M1 を使用しています。

機能テストを使用して、作成中の REST API のコントローラーをテストしています。テストをセットアップするときUser、管理者Roleを作成し、次に を作成しUserRoleます。Userスポック機能テストの内部に適切な資格情報が保持されていることを確認すると、すべて問題ないことがわかります。

ただし、認証GormUserDetailsService時に を呼び出しても何も得られませんUser.findWhere(username:<appropriate username>)。具体的な方法はGormUserDetailsServiceこちらから:

UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException {

    def conf = SpringSecurityUtils.securityConfig
    String userClassName = conf.userLookup.userDomainClassName
    def dc = grailsApplication.getDomainClass(userClassName)
    if (!dc) {
        throw new IllegalArgumentException("The specified user domain class '$userClassName' is not a domain class")
    }

    Class<?> User = dc.clazz

    User.withTransaction { status ->
        def user = User.findWhere((conf.userLookup.usernamePropertyName): username)
        if (!user) {
            log.warn "User not found: $username"
            throw new NoStackUsernameNotFoundException()
        }

        Collection<GrantedAuthority> authorities = loadAuthorities(user, username, loadRoles)
        createUserDetails user, authorities
    }
}

問題はUser.findWhere()、User インスタンスをデータベースにフラッシュしたことを機能テストで確認したにもかかわらず、呼び出しで何も見つからないことです。このメソッドのブロック内の呼び出しですべてのUserRoleUserを印刷しようとしましたが、まだ何も返されません。findAll()withTransaction

誰にも考えはありますか?自分ではない何かをあざける必要がありますか? @TestFor機能テストで@Mock注釈を使用しています。

アップデート

これが私の機能テストの簡単なバージョンです。

package com.help

import grails.plugins.rest.client.RestBuilder
import grails.plugins.rest.client.RestResponse
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
import groovy.json.JsonBuilder
import org.codehaus.groovy.grails.web.json.JSONObject
import spock.lang.Shared
import spock.lang.Specification

@TestFor(PersonController)
@Mock([Person, Role, PersonRole])
class PersonControllerSpec extends Specification {

    @Shared 
    RestBuilder rest = new RestBuilder(connectTimeout:10000, readTimeout:20000)
    @Shared 
    String baseUrl = "http://localhost:8080"
    @Shared
    int iterationCount = 0 

    Collection<Person> persons = []

    def setup() {
        Role adminRole = Role.findByAuthority("ROLE_ADMIN") ?: new Role(authority:"ROLE_ADMIN").save(failOnError:true, flush:true)
        Role userRole = Role.findByAuthority("ROLE_USER") ?: new Role(authority:"ROLE_USER").save(failOnError:true, flush:true)

        Person admin = new Person(name:"reserved", keyword:"admin", password:"password", email:"email@email.com", phone:"2222222222", personalPhoneNumber:"1112223333").save(failOnError:true, flush:true)
        Person user = new Person(name:"reserved", keyword:"user", password:"password", email:"email@email.com", phone:"2222222222", personalPhoneNumber:"1112223333").save(failOnError:true, flush:true)

        PersonRole.create(admin, adminRole, true)
        PersonRole.create(user, userRole, true)

        for (i in 0..20) {
            persons << new Person(name:"person-$iterationCount-$i", password:"password", keyword:"p-$iterationCount-$i", email:"email@email.com", phone:"1112223333", personalPhoneNumber:"1112223333")
        } 
        persons*.save(failOnError:true, flush:true)
    }

    def cleanup() { iterationCount++ }

    void "test listing persons"() {
        when: "we have an authenticated request"
        JsonBuilder jsonBuilder = new JsonBuilder()
        JSONObject json = jsonBuilder keyword:"admin", password: "password"
        RestResponse authResponse = rest.post("$baseUrl/api/login") {
            contentType "application/json"
            body(json)
        }

        then: "can access both restricted and public resources"
        ...
    }
}

の春のセキュリティ設定は次のConfig.groovyとおりです。

grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.help.Person'
grails.plugin.springsecurity.userLookup.usernamePropertyName = 'keyword'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.help.PersonRole'
grails.plugin.springsecurity.authority.className = 'com.help.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    '/':                              ['permitAll'],
    '/index':                         ['permitAll'],
    '/index.gsp':                     ['permitAll'],
    '/assets/**':                     ['permitAll'],
    '/**/js/**':                      ['permitAll'],
    '/**/css/**':                     ['permitAll'],
    '/**/images/**':                  ['permitAll'],
    '/**/favicon.ico':                ['permitAll'],
    '/dbconsole/**':                  ['ROLE_USER', 'ROLE_ADMIN']
]
grails.plugin.springsecurity.filterChain.chainMap = [
    '/v1/public/**': 'anonymousAuthenticationFilter,restTokenValidationFilter,restExceptionTranslationFilter,filterInvocationInterceptor',
    '/v1/**': 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter',  // v1 rest api stateless
    '/api/**': 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter',  // api utility methods stateless
    '/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'
]

grails {
    plugin {
        springsecurity {
            rest {
                login.useJsonCredentials = true
                login.usernamePropertyName = "keyword"
                token {
                    rendering.usernamePropertyName = "keyword"
                    rendering.authoritiesPropertyName = "roles"
                    rendering.tokenPropertyName = "access_token"
                    validation.useBearerToken = true
                    validation.enableAnonymousAccess = true
                }
            }
        }
    }
}
4

1 に答える 1

1

ドメイン クラスがサーバー インスタンスに表示されないという問題は、機能テストのサーバー インスタンスが別の jvm (フォークされた jvm モード) で実行されているという事実に関係しているため、すべての呼び出しをリモート。

に見られるように、次のようにリモートコントロールプラグインを使用することになりました(Grails 2.4.4を使用していることを思い出してください)BuildConfig.groovy

plugins {
    ...
    compile ":rest-client-builder:2.0.4-SNAPSHOT"
    compile ":remote-control:1.5"
    ...
}

上記のように、最新バージョンに更新した後に解決された正しい URL にリクエストを送信する際にいくつかの問題がありました。また、grails-remote-control url に対して springsecurity コア設定を permitAll に構成することを忘れないでください。

于 2015-03-09T23:37:24.027 に答える