1
我試圖用Spring Security 3插件配置我的Grails 3應用程序,以防止沒有特定權限的用戶訪問一組特定功能。 我使用了默認設置,其中User
,Role
和UserRole
域類(後者包括在下面),目的是廣泛使用@Secure
或@PreAuthorize
註釋。Grails&Spring Security - 基於附加屬性專門化用戶角色
後來出現了一個新需求:另一個域類是Project
(基本上可以授予您訪問一個或多個項目的權限),並且用戶可能具有項目特定的權限。
實施例:
- 有甲,乙,Ç作爲
Roles
- 用戶1具有甲和Ç角色
- 爲ProjectAlpha,我想要「覆蓋」用戶1的「默認」角色,以便他擁有A和B權限。
所以用戶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() } }
}
}
感謝您的建議!在詳細瞭解了一下之後,我瞭解ACL插件可以讓你爲域類和服務定義臨時訪問規則,但爲了方便起見,我寧願將這個邏輯放在控制器級別。我想我會定義類似'def action(){if(checkUserRole(user,allowedRoles)){/ * set 401 status */return}/* stuff * /}' – ilPittiz