【问题标题】:Grails & Spring Security - specialize User-Role based on additional propertyGrails & Spring Security - 基于附加属性专门化用户角色
【发布时间】:2016-05-19 06:40:57
【问题描述】:

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

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

例子:

  • ABCRoles
  • User1 具有 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() } }
    }

}

【问题讨论】:

    标签: grails spring-security


    【解决方案1】:

    听起来你需要the ACL plugin。它将允许您为不同用户配置单个域类实例的权限。角色应该更粗粒度,但如果你想配置读取/编辑/删除/管理/等。权限,ACL 更合适。

    【讨论】:

    • 感谢您的建议!经过更详细的检查后,我了解到 ACL 插件可以让您为域类和服务定义临时访问规则,但为了方便起见,我宁愿将此逻辑保留在控制器级别。我想我会定义类似def action() { if(checkUserRole(user, allowedRoles)) { /* set 401 status */ return } /* stuff */ }
    猜你喜欢
    • 2016-10-14
    • 2020-12-18
    • 2015-01-16
    • 2014-02-27
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    相关资源
    最近更新 更多