0

grails フレームワーク (2.5.0) で Spring Security Plugin (2.0.0) と Spring Authentication Rest Plugin (1.5.3) を使用してトークン ベースの認証を実装しようとしています。ヘッダー フィールド「x-auth-token」をトークンに設定し、ターゲット コントローラー URL に投稿します。ただし、IDE (Intellij IDEA) はこのエラー メッセージを表示します。

| Error 2016-07-12 15:58:27,864 [http-bio-8080-exec-10] ERROR [/hello_world].
[default]  - Servlet.service() for servlet [default] in context with path [/hello_world] threw exception
Message: Cannot invoke method loadUserByToken() on null object
Line | Method
->>   55 | authenticate in grails.plugin.springsecurity.rest.RestAuthenticationProvider
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     75 | doFilter     in grails.plugin.springsecurity.rest.RestTokenValidationFilter
|     53 | doFilter . . in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
|    143 | doFilter     in grails.plugin.springsecurity.rest.RestAuthenticationFilter
|     62 | doFilter . . in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
|     80 | doFilter     in grails.plugin.springsecurity.rest.RestLogoutFilter
|     59 | doFilter . . in grails.plugin.springsecurity.web.SecurityRequestHolderFilter
|     82 | doFilter     in com.brandseye.cors.CorsFilter
|   1142 | runWorker .  in java.util.concurrent.ThreadPoolExecutor
|    617 | run          in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run . . . .  in java.lang.Thread

この loadUserByToken() メソッドを確認したところ、tokenStorageService で呼び出されます。この tokenStorageService が null オブジェクトである理由がわかりません。Spring Security と Spring Security Plugin は次のように構成されています。

Config.groovy

// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'hello_world.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'hello_world.UserRole'
grails.plugin.springsecurity.authority.className = 'hello_world.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    '/':                ['permitAll'],
    '/index':           ['permitAll'],
    '/index.gsp':       ['permitAll'],
    '/assets/**':       ['permitAll'],
    '/**/js/**':        ['permitAll'],
    '/**/css/**':       ['permitAll'],
    '/**/images/**':    ['permitAll'],
    '/**/favicon.ico':  ['permitAll'],
    '/api/login':       ['permitAll']
]

grails {
    plugin {
        springsecurity {

            filterChain.chainMap = [
                    '/api/guest/**': 'anonymousAuthenticationFilter,restTokenValidationFilter,restExceptionTranslationFilter,filterInvocationInterceptor',
                    '/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter',  // Stateless chain
                    '/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'                                                                          // Traditional chain
            ]

            providerNames = ['restAuthenticationProvider','daoAuthenticationProvider', 'rememberMeAuthenticationProvider']

            auth.loginFormUrl = '/login/auth'

            useSecurityEventListener = true

            onAuthenticationSuccessEvent = { e, appCtx ->
                // handle AuthenticationSuccessEvent

                System.out.println("Authentication Succeeded");
            }

            onAuthenticationSwitchUserEvent = { e, appCtx ->
                // handle AuthenticationSwitchUserEvent
            }

            onAuthorizationEvent = { e, appCtx ->
                // handle AuthorizationEvent
            }

            onRestTokenCreationEvent = { e, appCtx ->

                System.out.println("Token Created")
            }

            apf {
                filterProcessesUrl = '/api/login'
                allowSessionCreation = false
//                usernamePropertyName = 'username'
//                passwordPropertyName = 'password'
            }

            rest {

                active = true

                login {
                    active = true
                    endpointUrl = '/api/login'
                    failureStatusCode = 401
                    useJsonCredentials = true
                    usernamePropertyName = 'username'
                    passwordPropertyName = 'password'
                }

                token {

                    validation {
                        active = true
                        endpointUrl = '/api/validate'
                        headerName = 'x-auth-token'
                        useBearerToken = false
                        tokenPropertyName = 'access_token'
                        enableAnonymousAccess = true
                    }

                    generation {
                        active = true
                        useSecureRandom = true
                        useUUID = false
                    }

                    rendering {
                        usernamePropertyName = 'username'
                        authoritiesPropertyName = 'roles'
                        tokenPropertyName = 'token'
                    }

                    storage {
                        active = true
                        useGorm = true

                        gorm {
                            tokenDomainClassName = 'hello_world.AuthenticationToken'
                            tokenValuePropertyName = 'tokenValue'
                            usernamePropertyName = 'username'
                        }
                    }
                }
            }
        }
    }
}

resources.groovy

import grails.plugin.springsecurity.rest.RestAuthenticationProvider
beans = {
    restAuthenticationProvider(RestAuthenticationProvider);
}

データベースを確認したところ、トークンは authentication_token テーブルに保存されています。私はgrailsを初めて使用し、何時間も検索してきましたが、まったく手がかりがありません。誰でも私を助けることができますか?とても有難い。

他に何か必要な場合は、お知らせください。

4

1 に答える 1

1

同じ問題を抱えている人のために、何度も試した後、私は最終的にこれを理解しました. resources.groovy で restAuthenticationProvider を宣言するべきではないようで、config.groovy の grails.plugin.springsecurity.providerNames に restAuthenticationProvider を追加するべきではないようです。spring-security-core および spring-security-rest の完全な構成は次のとおりです。

config.groovy

grails {
    plugin {
        springsecurity {

            useSecurityEventListener = true

            filterChain {
                chainMap = [
                        '/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter',  // Stateless chain
                        '/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'                                                                          // Traditional chain
                ]
            } //filterChain

            apf {
                filterProcessesUrl = '/api/login'
            } //apf

            rest {

                login {
                    active = true
                    useRequestParamsCredentials = false
                    useJsonCredentials = true
                    usernamePropertyName = 'j_username'
                    passwordPropertyName = 'j_password'
                    endpointUrl = '/api/login'
                } //login

                logout {

                } //logout

                token {

                    validation {
                        active = true
                        endpointUrl = '/api/validate'
                        useBearerToken = false
                        headername = 'X-Auth-Token'
                    } //validation

                    generation {
//                        active = true
//                        useSecureRandom = true;
//                        useUUID = false;
                    }

                    rendering {
                        usernamePropertyName = 'username'
                        authoritiesPropertyName = 'roles'
                        tokenPropertyName = 'token'
                    }

                    storage {
//                        useJWT = true;
                    } //storage
                } //token
            } //rest

            cors.headers = ['Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Auth-Token']
        } //springsecurity
    } //plugin
} //grails

フィールド「j_username」と「j_password」を使用して、ユーザー名とパスワードをjson形式で送信する必要があり、json形式でトークンが返されます。次に、このトークンをヘッダー フィールド「X-Auth-Token」に含めて、クエリを実行する API にリクエストを送信します。

spring-security-core プラグインの初期化については、 http: //grails-plugins.github.io/grails-spring-security-core/v2/guide/single.html#tutorialsを参照してください。

私のコード全体は github で入手できます: https://github.com/xixinhe/api_token_authentication

コードを実行する前に、Oracle mysql 5 をインストールしてください。

スタック オーバーフローのルールに違反するような記述があれば、お知らせください。変更します。

私は英語のネイティブ スピーカーではありません。くだらない英語をお許しください。

ありがとう、

于 2016-07-15T05:21:39.733 に答える