3

私の grails アプリでは、以下に示すようにカスタム認証成功ハンドラー (resources.groovy 内) を作成して、承認後のワークフローをカスタマイズしました。

authenticationSuccessHandler (MyAuthSuccessHandler) {
    def conf = SpringSecurityUtils.securityConfig
    requestCache = ref('requestCache')
    defaultTargetUrl = conf.successHandler.defaultTargetUrl
    alwaysUseDefaultTargetUrl = conf.successHandler.alwaysUseDefault
    targetUrlParameter = conf.successHandler.targetUrlParameter
    useReferer = conf.successHandler.useReferer
    redirectStrategy = ref('redirectStrategy')
    superAdminUrl = "/admin/processSuperAdminLogin"
    adminUrl = "/admin/processAdminLogin"
    userUrl = "/admin/processUserLogin"
}

上記のクロージャの最後の 3 行からわかるように、ログイン ユーザーに付与されたロールに応じて、カスタム UserSessionBean が作成されてセッションに保存される AdminController内の別のアクションに彼女をリダイレクトしています。

私のアプリでは次のような通常のログインケースでうまく機能します:

  1. http://localhost:8080/my-app/ユーザーは、またはいずれかの方法でアプリにアクセスしますhttp://localhost:8080/my-app/login/auth
  2. 有効なログイン ID とパスワードを入力して続行します。
  3. アプリは内部的に MyAuthSuccessHandler にアクセスし、このユーザーに付与されたロールを考慮して AdminController にリダイレクトします。
  4. UserSessionBean が作成され、セッションに格納されます
  5. ユーザーはアプリのホームページに移動します

上記のフローで正しくアクセスさMyUserDetailsServiceれる拡張によるカスタムも作成しました。GormUserDetailsService

問題のシナリオ:ユーザーがアプリ内の保護されたリソース (この場合、コントローラーは注釈
で保護されています) に直接アクセスしているとします。@Secured

  1. ユーザーのクリックhttp://localhost:8080/my-app/inbox/index
  2. アプリは彼女をにリダイレクトしますhttp://localhost:8080/my-app/login/auth
  3. ユーザーは有効なログイン ID とパスワードを入力します
  4. ユーザーはhttp://localhost:8080/my-app/inbox/index

このMyAuthSuccessHandlerプロセスでは完全にスキップされるため、UserSessionBeanが作成されず、 UserSessionBeanにアクセスする場所でさらに使用するとエラーが発生します。

質問:

  1. MyAuthSuccessHandler問題のシナリオでは、ログイン時にリダイレクトするターゲット URL があるため、アプリは をスキップしますか?
  2. MyAuthSuccessHandlerターゲット URL が存在する場合でも、プロセスを常に通過させることはできますか?
  3. 2 に対する答えが「いいえ」の場合、 UserSessionBeanを作成する方法と場所に関する代替手段はありますか?
4

2 に答える 2

4

元のユーザーが要求した URL を中断することなく、ログイン後のプロセスを処理するカスタマイズされた eventListener を実装できます。

config.groovy に構成項目を挿入します。

grails.plugins.springsecurity.useSecurityEventListener = true

resources.groovy に、次のような Bean を追加します。

import com.yourapp.auth.LoginEventListener
beans = {
    loginEventListener(LoginEventListener)
}

そして、次のように src/groovy に eventListener を作成します。

package com.yourapp.auth
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent
import org.springframework.web.context.request.RequestContextHolder as RCH

class LoginEventListener implements
    ApplicationListener<InteractiveAuthenticationSuccessEvent> {    

    //deal with successful login    
    void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
        User.withTransaction { 
            def user = User.findByUsername(event.authentication.principal.username)
                    def adminRole = Role.findByAuthority('ROLE_ADMIN')
                    def userRole = Role.findByAuthority('ROLE_USER')
                    def session = RCH.currentRequestAttributes().session      //get httpSession
                    session.user = user
                    if(user.authorities.contains(adminRole)){
                        processAdminLogin()
                    }
                    else if(user.authorities.contains(userRole)){
                        processUserLogin()
                    }
        }
    }

    private void processAdminLogin(){    //move admin/processAdminLogin here
          .....
    }

    private void processUserLogin(){    //move admin/processUserLogin here
          .....
    }
}

終わり。

于 2012-12-17T05:44:34.390 に答える
3

1) はい、「オンデマンド」ログインであるためです。

2) はい、常にデフォルトを使用するように設定できます。Springセキュリティ プラグインには、「successHandler.alwaysUseDefault」の設定があり、それを true に変更すると、デフォルトで false になります。

また、詳細が必要な場合は、Spring ドキュメントの「デフォルトのログイン後の宛先の設定」セクションを確認してください。

3) ユーザー セッション Bean を作成してから元の URL にリダイレクトする場合は、以前のフィルターで Bean を作成するか、カスタムUserDetailsS​​erviceを介して必要なデータを公開する 2 つのオプションがあります。個人的には、カスタム詳細サービスのルートに行きます。

于 2012-12-07T06:25:55.217 に答える