2012-12-18 86 views
9

春季安全是偉大基於角色的授權,但它似乎功虧一簣,當談到基於規則的授權。當然,有些方法可以通過SpEL來實現,但是通過這種方式似乎會將註釋鎖定在註釋中,因爲將邏輯拉出到服務中會更好,因此多個位置可以使用相同的邏輯。如何在Grails中使用Spring Security進行基於規則的授權?

似乎有成爲一些waystogoabout在自己的規劃環境地政司表達增加,但關注的是特別清楚,即使是那些意義,我似乎功虧一簣。我想,給出如何靈活 Groovy是,有必須是一種不必一起硬編碼的依賴關係,而是在運行時獲得安全規則(或SpEL擴展)。

雖然不理想,但即使像定義所有需要的新規則和注入mixin(即SecurityExpressionRoot.mixin MyRule1)這樣看起來很簡單的東西也是一個好的開始,但這似乎並不奏效。

有誰知道這樣做的例子嗎?如果沒有,我怎麼可以自己做這件事呢?


一(簡化的)例子:用戶只能採取的特定動作與對象如果3 4的字段具有超過特定閾值的值,但僅當對象是(即執行服務的方法。)少於3天:

class MyRule { 

    boolean canTakeAction(Person person, MyThing myThing) { 
     int numFieldsWithValues = 0 
     if (myThing.field1 != null) { numFieldsWithValues++ } 
     if (myThing.field2 != null) { numFieldsWithValues++ } 
     if (myThing.field3 != null) { numFieldsWithValues++ } 
     if (myThing.field4 != null) { numFieldsWithValues++ } 

     return (numFieldsWithValues > 3) && (ageInDays(myThing) < 3) 
    } 

    int ageInDays(MyThing myThing) { 
     ... 
    } 
} 

而這是一個更簡單的規則。

回答

2

基於角色的授權是最簡單但不太靈活的方式。與此相反的是Spring安全ACL system。 ACL允許您定義允許被允許執行的功能什麼是哪些是在運行時對象。另一方面,這需要更復雜的設置。還有一個grails plugin for this

在SpEL表達式中使用註釋的方式介於這兩種選擇之間。它們比簡單角色更靈活,比ACL更簡單。如果您正在尋找Grails中的方法安全性介紹,可能this我之前寫過的博文可以幫助您。

+0

就像我在我的問題中所說的那樣,基於角色的授權(哪些ACL只是更精細的版本)在您需要的時候非常棒,而Spring Security擅長這一點。不幸的是,我的要求比基於角色的輕鬆處理要複雜得多。 SpEL規則更多的是我所追求的,但我需要能夠在應用程序中的多個位置獲得相同的複雜規則,並且SpEL規則的複製粘貼不能是最好的方式。 – cdeszaq

+0

Imho ACL不是一個更加細化的基於角色的系統。它允許您定義允許誰在對象上執行特定操作的權限(獨立於任何角色)。你能舉一個你複雜規則的例子嗎? – micha

+0

一個示例(簡化):如果4個字段中的3個字段的值超過特定閾值,但只有該對象小於3天時,用戶才能使用對象執行特定操作(即執行服務方法)。這是更簡單的規則之一。 – cdeszaq

1

您可以在Requestmap中管理您的規則,該規則提供動態配置功能。

例如,在Config.groovy中定義的安全類型requestmap第一:

grails.plugins.springsecurity.securityConfigType = "Requestmap" 

那麼你可能有Requestmap領域類相似,用戶和角色,像這樣:

package com.app.auth 
class Requestmap { 

    String url 
    String configAttribute 

    static mapping = { 
     cache true 
    } 

    static constraints = { 
     url blank: false 
     configAttribute blank: false 
    } 
} 

現在,因爲用戶,角色和Reqestmap都保存在數據庫中,您可以輕鬆地通過某些控制器中的CRUD操作更改規則,而無需重新部署或重新啓動服務。就像這樣:

class RequestmapController { 

def springSecurityService 

... 

def save = { 
    def requestmapInstance = new Requestmap(params) 
    if (!requestmapInstance.save(flush: true)) { 
     render view: 'create', model: [requestmapInstance: requestmapInstance] 
     return 
    } 

    springSecurityService.clearCachedRequestmaps()  //This is important: to refresh the requestmap. Without it the rules remain unchanged. 
    flash.message = "${message(code: 'default.created.message', args: [message(code: 'requestmap.label', default: 'Requestmap'), requestmapInstance.id])}" 
    redirect action: show, id: requestmapInstance.id 
    } 
} 

在視圖層,你可以管理你的菜單,按鈕和其他元素使用彈簧安全標籤一樣需要授權:

<sec:access url="foo/bar"> 
    <li><g:link class="list" controller="foo" action="bar">Bar action</g:link></li> 
</sec:access> 

因此,意見也符合授權規則。

此外,還有一個Hierarchical Roles功能可以用來減少請求映射中的混亂。

+0

正如我在問題中提到的和@micha所提及的,角色不足以滿足我的需求。我已經添加了一個簡化版本的例子,我需要使用這些規則來保護多個不同地方的方法訪問。如果你所描述的可以處理,請展開你的例子來展示。 – cdeszaq

+0

我認爲你可以使用[Filters](http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/16%20Filters.html)來自定義你的示例中指定的規則。 – coderLMN

+0

過濾器不能應用於服務方法調用,僅適用於Web請求。我需要通過Spring Security應用安全規則(或者至少在任何地方Spring Security都允許我使用SpEL來應用安全規則),所以過濾器也不夠用,儘管我喜歡這個想法,並且它可能適用於某些規則。 – cdeszaq

0

從您發佈的示例中,GContracts可能是您要查找的內容。在運行GContract閉包時,您只需要弄清楚如何訪問Principal,但這可能與將其作爲參數傳遞給合同化方法一樣簡單。

+0

看起來很有希望,但GContracts [已知與Grails存在問題](https://github.com/andresteingress/gcontracts/wiki/GContracts-in-Spring-and-Grails-Applications)和Spring更普遍。我不確定我會遇到這個問題,但是必須有一種方法來使用Spring Security中內置的SpEL。 – cdeszaq