Grails & Spring Security - 基于附加属性专门化用户角色



我正在尝试使用Spring Security 3插件配置我的Grails 3应用程序,以防止没有特定权限的用户访问一组特定功能。我使用了默认设置,包括UserRoleUserRole域类(后者包含在下面(,目的是广泛使用@Secure@PreAuthorize注释。

后来,出现了一个新的要求:Project另一个域类(基本上可以授予您对一个或多个项目的访问权限(,并且用户可能具有特定于项目的权限。

例:

  • A,B,C作为Roles
  • 用户 1 具有 AC 角色
  • 对于 ProjectAlpha,我想"覆盖">User1 的"默认"角色,以便他拥有 AB 权限。

因此,User1ProjectAlpha 的"真实"权限必须在具有该Project引用的UserRole条目中找到。

作为第一件事,我即将为类添加新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插件。它将允许您为不同用户配置单个域类实例的权限。角色应该更粗粒度,但如果要配置读取/编辑/删除/管理员/等权限,ACL 更适合。

最新更新