2016-02-09 59 views
1

我試圖用Spring Security 3插件配置我的Grails 3應用程序,以防止沒有特定權限的用戶訪問一組特定功能。 我使用了默認設置,其中User,RoleUserRole域類(後者包括在下面),目的是廣泛使用@Secure@PreAuthorize註釋。Grails&Spring Security - 基於附加屬性專門化用戶角色

後來出現了一個新需求:另一個域類是Project(基本上可以授予您訪問一個或多個項目的權限),並且用戶可能具有項目特定的權限。

實施例:

  • Ç作爲Roles
  • 用戶1具有Ç角色
  • ProjectAlpha,我想要「覆蓋」用戶1的「默認」角色,以便他擁有AB權限。

所以用戶1的‘真實’的ProjectAlpha權限將有UserRole項與Project參考中被發現。

作爲第一件事,我正要爲UserRole類增加一個新的Project project屬性,其中project是在攔截器中預先計算的。但是,我無法弄清楚這項任務的最佳方法(甚至是可行性)。

任何建議,歡迎提前致謝!

package myApp 

import grails.gorm.DetachedCriteria 
import groovy.transform.ToString 

import org.apache.commons.lang.builder.HashCodeBuilder 

@ToString(cache=true, includeNames=true, includePackage=false) 
class UserRole implements Serializable { 

    private static final long serialVersionUID = 1 

    static constraints = { 
     role validator: { Role r, UserRole ur -> 
      if(ur.user == null || ur.user.id == null) return 
      boolean existing = false 
      UserRole.withNewSession { 
       existing = UserRole.exists(ur.user.id, r.id) 
      } 
      if(existing) { 
       return 'userRole.exists' 
      } 
     } 
    } 

    static mapping = { 
     id composite: ['user', 'role'] 
     version false 
    } 

    User user 
    Role role 

    /*UserRole(User u, Role r) { 
     this() 
     user = u 
     role = r 
    }*/ 

    @Override 
    boolean equals(other) { 
     if(!(other instanceof UserRole)) { 
      return false 
     } 

     other.user?.id == user?.id && other.role?.id == role?.id 
    } 

    @Override 
    int hashCode() { 
     def builder = new HashCodeBuilder() 
     if(user) builder.append(user.id) 
     if(role) builder.append(role.id) 
     builder.toHashCode() 
    } 

    static UserRole get(long userId, long roleId) { 
     criteriaFor(userId, roleId).get() 
    } 

    static boolean exists(long userId, long roleId) { 
     criteriaFor(userId, roleId).count() 
    } 

    private static DetachedCriteria criteriaFor(long userId, long roleId) { 
     UserRole.where { 
      user == User.load(userId) && 
      role == Role.load(roleId) 
     } 
    } 

    static UserRole create(User user, Role role, boolean flush = false) { 
     def instance = new UserRole(user: user, role: role) 
     instance.save(flush: flush, insert: true) 
     instance 
    } 

    static boolean remove(User u, Role r, boolean flush = false) { 
     if(u == null || r == null) return false 

     int rowCount = UserRole.where { user == u && role == r }.deleteAll() 

     if(flush) { UserRole.withSession { it.flush() } } 

     rowCount 
    } 

    static void removeAll(User u, boolean flush = false) { 
     if(u == null) return 

     UserRole.where { user == u }.deleteAll() 

     if(flush) { UserRole.withSession { it.flush() } } 
    } 

    static void removeAll(Role r, boolean flush = false) { 
     if(r == null) return 

     UserRole.where { role == r }.deleteAll() 

     if(flush) { UserRole.withSession { it.flush() } } 
    } 

} 

回答

2

這聽起來像你需要the ACL plugin。它將允許您爲不同用戶配置單個域類實例的權限。角色應該更粗糙,但是如果你想配置讀/編輯/刪除/管理員等。權限,ACL更合適。

+0

感謝您的建議!在詳細瞭解了一下之後,我瞭解ACL插件可以讓你爲域類和服務定義臨時訪問規則,但爲了方便起見,我寧願將這個邏輯放在控制器級別。我想我會定義類似'def action(){if(checkUserRole(user,allowedRoles)){/ * set 401 status */return}/* stuff * /}' – ilPittiz

相關問題