2009-01-29 63 views
4

我寫Grails中一個小的web應用,並確保所有用戶都我用下面的篩選認證從過濾器定義控制器訪問的變量:Grails中

class LoginFilters { 
    static filters = { 
    loginCheck(controller:'*', action:'*') { 
     before = { 
     if (session.user_id) { 
      request.user = User.get(session.user_id) 
     } else if (!actionName.equals("login")) { 
      redirect(controller: "login", action: "login") 
      return false 
     } 
     } 
    } 
    } 
} 

和所有的控制器方法開始讀取請求對象的用戶屬性:

def actionName = { 
    def user = request.user 
    ... 
} 

上面的代碼有效,但我寧願避免所有控制器方法中的重複代碼。過濾器是否可以將用戶對象綁定到名爲「user」的變量而不是「request.user」,這可以從所有控制器訪問?

我知道可能存在一些範圍問題,這使得這種情況變得不可能,但是Grails框架似乎能夠在引擎蓋下創建相當多的魔法,所以我認爲這可能值得提問。

回答

1

在控制器使用beforeInterceptor可能會有幫助:

class LoginController { 

    def user 

    def beforeInterceptor = { 
     user = request.user 
    } 

    def index = { 
     render text:"index: ${user}"   
    } 

    def test = { 
     render text:"test: ${user}"   
    } 
} 
0

我認爲你可以做到這一點,但它真的值得麻煩?在我看來,你唯一的優勢是輸入「user」而不是「request.user」。收益不大。無論如何,我認爲您可以按照用戶指南的「12.7在運行系統中添加動態方法」中的說明進行操作。我認爲,如果您創建了一個動態方法「getUser(){return request.user}」,那麼Groovy JavaBeans getter/setter訪問將允許您以您想要的方式簡單引用「user」。

如果您確實添加了動態方法,您可能需要跳過篩選器並在動態方法中完成所有操作。

1

我認爲這通常不是一個好主意插入用戶對象放入請求對象每次:

請求壽命很短,所以你可能最終使往返於高速緩存或更糟的數據庫在每個http請求中檢索一個對象,你可能甚至不需要這個對象,並且在之後立即被刪除。所以如果你必須的話,最好將整個對象存儲在會話中,而不僅僅是id。

通常,我建議你編寫一個AuthenticationService的方法isLoggedIn(),該方法在用戶通過身份驗證時返回true,並返回此對象的方法getLoggedInUser()

class AuthenticationService { 
    def transactional = false 
    boolean isLoggedIn() { return session.user_id } 
    def getLoggedInUser() { return User.get(session.user_id) } 
} 

然後使用過濾器重定向如果未通過身份驗證,也許攔截器,用於存儲本地參考user = authenticationService.loggedInUser。但我也不認爲這是最好的方式。我建議你創建一個抽象AuthenticationAwareController作爲在SRC/Groovy中所有的控制器基類,並有有像user

class AuthenticationAwareController { 
    def authenticationService 
    def getUser() { return authenticationService.loggedInUser() } 
} 

這樣的簡便方法,你可以改變你介意存儲用戶,但是你喜歡,不必更改您的代碼。此外,您還可以從Hibernate中的緩存中受益,該緩存在不同會話之間共享已檢索的用戶對象實例,因此可避免數據庫往返。

您仍然應該檢查檢索到的用戶對象的有效性,如果檢索不成功,則會拋出AuthenticationException。 (也許像AuthenticationService.getLoggedInUser(failOnError = false)。)

你甚至可以使這個Service/ControllerBase成爲一個小插件,在每個應用程序上重複使用或直接使用spring安全插件... ;-)