2012-12-07 25 views
3

在我的grails應用程序中,我通過編寫自定義auth成功處理程序(在resources.groovy中)來定製後期授權工作流程,如下所示。Grails Spring Security:使用目標URL登錄跳過post驗證工作流程

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

,你可以從最後三行在封閉上面,這取決於授予用戶的日誌,我重定向她到AdminController在其中創建一個自定義UserSessionBean和儲存中分離行動中的作用在會議中。

它工作正常的經常登錄的情況下這在我的應用程序是像這樣:

  1. 用戶通過任一http://localhost:8080/my-app/http://localhost:8080/my-app/login/auth
  2. 她進入她的有效登錄ID和密碼,進行涉及到的應用程序。
  3. 考慮授予此用戶的角色,應用程序在內部訪問重定向到AdminController的MyAuthSuccessHandler。
  4. 的UserSessionBean通過延長GormUserDetailsService這是在上述流程中正確地訪問創建並存儲它在會話
  5. ,用戶被引導到應用程序主頁

我也寫一個自定義的MyUserDetailsService

問題方案:
考慮一個用戶直接訪問(在這種情況下,所述控制器被固定與@Secured註解)受保護的資源的應用程序內。

  1. 用戶點擊http://localhost:8080/my-app/inbox/index
  2. 應用重定向她http://localhost:8080/my-app/login/auth
  3. 用戶輸入
  4. 用戶被引導到http://localhost:8080/my-app/inbox/index

MyAuthSuccessHandler在這個過程中完全忽略了有效的登錄ID和密碼因此我的UserSessionBean不會導致進一步使用時出錯在訪問UserSessionBean的地方。

問題:

  1. 在問題的情況下,不應用跳過MyAuthSuccessHandler因爲有一個目標URL爲它在登錄時重定向到?
  2. 即使目標URL存在,我們是否可以強制該進程始終通過MyAuthSuccessHandler
  3. 如果對2的回答爲否,是否還有其他方法可以創建UserSessionBean
+0

'conf.successHandler.alwaysUseDefault'設置爲'true'嗎? – GalmWing

+0

我沒有改變它。它處於默認狀態。 –

回答

4

您可以實現自定義eventListener來處理登錄後過程,而不會中斷原始用戶請求的url。

Config.groovy中,插入一個配置項:

grails.plugins.springsecurity.useSecurityEventListener = true 

在你resources.groovy,添加一個bean是這樣的:

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

,並創建一個SRC事件監聽/ Groovy中這樣:

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 
      ..... 
    } 
} 

完成。

+0

這似乎是一個更好的選擇,除了是否有方法訪問此類中的HttpSession?我必須在那裏存儲一個UserSessionBean,如上所述 –

+1

@SagarV當然,你可以像'def session = RequestContextHolder.currentRequestAttributes()。session'那樣訪問它。我更新了我的示例以顯示該案例。 – coderLMN

+0

謝謝@Jinzhao它工作! –

3

1)是的,因爲它是「按需」登錄。

2)是的,你可以設置它始終使用默認值。彈簧安全插件有一個設置爲「successHandler.alwaysUseDefault」更改爲true它默認爲false。

此外,如果你需要更多的細節檢查出春天docs認準設置一個默認的提交登陸目標部分。 3)如果你想繼續創建用戶會話bean,然後重定向到原始URL,你有兩個選擇,在前面的過濾器中創建bean,或者通過自定義的UserDetailsService公開所需的數據。就我個人而言,我會去一個自定義詳細信息服務的路線。

+0

感謝您的快速回答。我不知道alwaysUseDefault配置值,現在已經相應地設置了它。儘管現在它總是會重定向到defaultUrl,在這種情況下是應用程序主頁。有沒有一種方法可以將用戶重定向到所請求的URL,其中alwaysUseDefault設置爲true? –

+0

我編輯了答案,併爲選項3添加了一個答案,這可能更符合您的要求。 –

+1

@JeffBeck,我想他已經做到了。 – GalmWing