2014-12-04 85 views
1

使用Spring Security插件的Grails: Version: 2.0-RC2Grails的Spring Security的表達 - 如何訪問方法參數

對於我的控制器,我使用的@Secured註解。 有沒有辦法從spring安全表達式中訪問方法參數? #paramName不適合我。

@Secured(['ROLE_ADMIN',"hasRole('ROLE_USER') && @permissionService.updateAllowed(#myInstance)"]) 
def update(Bug myInstance) { 

問題:將myInstance爲空!

軟件我使用:

的Grails:2.4.3
的IntelliJ 14
JDK 8

+1

這應該工作,這是正確的語法。嘗試運行'grails clean'並查看完整的重新編譯是否有幫助 – 2014-12-04 16:42:54

+0

Hey @Burt,謝謝你的回覆。我做了一個Grails clean-all。但它沒有改變。 #myInstance仍然爲空。在更新方法#myInstance不爲空!只有在表達式上下文中#myInstance爲空。也許這不適用於控制器? – testbug 2014-12-05 14:41:09

回答

2

我沒有注意到,你是在一個控制器這樣做 - 有一個爲不支持方法參數在註釋的控制器中。原因在於,在傳統的Spring Security中,註釋被應用到Spring Beans並且bean被代理,並且代理在調用方法之前執行安全性檢查,並且只在檢查通過時調用真正的方法。這對於Spring MVC控制器非常有效,因爲它們是常規的Java類,而且在Grails服務中也是如此,因爲Grails沒有太多的服務添加到服務中 - 它們實際上只是自動註冊爲Spring Bean的常規Groovy類,而且默認情況下是事務性的。

但控制器很奇怪。實際上在任何Grails應用程序中都有一個SpringMVC控制器,並且它由Grails在內部創建和使用。它與SpringMVC的其餘部分進行交互,並委託給與當前請求的url映射規則最匹配的控制器來完成其工作,並使用它來創建Spring期望的ModelAndView。此外,爲了支持數據綁定,在編譯過程中會在代碼上運行AST轉換,這會爲每個帶有args的方法創建一個無參數方法,這就是Grails內部請求處理代碼所調用的方法。它執行數據綁定和類型轉換,並調用「真實」方法來處理請求。

Spring Security中使用方法args的支持取決於編譯代碼中的調試信息,通常這是不可用的,因爲它很少需要 - javac在編譯時爲我們連接所有東西,並獲得方法arg來自方法之外並不經常需要。 Grails確實保留了這個調試信息 - 這就是爲什麼它可以在服務中工作 - 但它看起來像AST不是。有可能得到這個工作,但我不知道它是否會涉及或將涉及什麼,並且說實話,對於不會使用太多功能的功能可能會有很多工作。

但是,您可以重新執行檢查以將params傳遞給服務,並讓它查找Bug實例,然後執行檢查。您可以從服務接入參數,可以因此沒有必要通過任何爲ARGS:

import org.springframework.web.context.request.RequestContextHolder 
... 
def params = RequestContextHolder.requestAttributes.params 
+0

嘿,伯特,將訪問控制器上的方法參數在Grails 3工作? – 2015-03-23 02:27:45

+1

當表達式被評估時,'params'(從RequestContextHolder.requestAttributes.params'中取出)還沒有設置'controller','action'和'id',所以我甚至無法加載'myInstance'手。有沒有辦法解決這個問題? – 2015-05-27 19:05:48

0

我設法在評論中接受的答案中描述的問題的方法。在規劃環境地政司表達式中使用#此:

@Secured('@securityService.userCanEditOffer(#this)') 
def edit(int id) {..} 

然後在你的服務中創建這樣的方法:

def userCanEditOffer(WebSecurityExpressionRoot webSecurityExpressionRoot) { 
    UrlMappingInfo urlMappingInfo = Holders.applicationContext.grailsUrlMappingsHolder.match(webSecurityExpressionRoot.request.forwardURI.substring(webSecurityExpressionRoot.request.contextPath.length())) 
    userCanEditOffer(Integer.valueOf(urlMappingInfo.params.id)) 
} 

@Transactional(readOnly = true) 
def userCanEditOffer(Integer id) { .. } 

裏面ulrMappingInfo.params你有ID,動作和控制器!

相關問題