我想实现本文中讨论的基于权限的访问控制。
我不熟悉实施 - 有没有关于如何从头到尾实施的详细示例?
你见过Spring 安全插件吗? 主要文档在这里
就像在这篇文章中一样,您也可以考虑使用 Shiro 插件。我发现 Spring 安全插件更简单,但 Shiro 插件确实有一些优势,如帖子中所述。
我刚刚(大部分)解决了这个问题,所以我在这里发布以供参考。此解决方案适用于 Grails 2.2.4 和 Spring Security 2.0 RC
1) 安全域模型 您按照文章中的描述为您的安全域类建模,因此您最终将拥有这些域: - Permission - Role - RolePermission - User - UserRole
2) 查询用户权限 您确保您的 User 类返回 Permissions 而不是 Roles 作为 getAuthorities() 方法中的权限:
/**
* Gets authorities for the user.
*
* It will return all of the Permissions of the User assigned by the Roles
* which the User has
*/
Set<Permission> getAuthorities() {
Set allPermissions = []
// Collect all Roles of the User
UserRole.findAllByUser(this).each { userRole ->
// Collect all Permissions from the Role
Role role = userRole.role
// Returning the collected permissions
RolePermission.findAllByRole(role).each { rp ->
allPermissions.add(rp.permission)
}
}
return allPermissions
}
3) Spring 安全配置
我在我的 Config.groovy 中有这个用于 Spring Security 配置(省略了不相关的部分):
grails {
plugin {
springsecurity {
...
userLookup {
userDomainClassName = 'limes.security.User'
}
authority {
nameField = 'name'
className = 'limes.security.Permission'
}
...
}
}
}
一个重要的亮点是 authority.nameField 必须符合您的 Permission 类。name 属性在我的模型(和文章)中称为“name”。
自然,您将 Permission 类设置为 authority.className 以使其符合 User.getAuthorities() 的返回值。
4) 在安全表达式中使用
上述解决方案并未解决 Grails Spring Security 插件只能使用以“ROLE_”开头的权限名称的限制。
因此,如果您想调用“PERM_PERMISSION1”之类的权限,那么您必须编写 EL 表达式以在任何地方进行检查(尤其是在控制器 @Secured 注释和静态 url 规则上)。
所以而不是
@Secured(["PERM_PERMISSION1"])
你写
@Secured(["hasRole('PERM_PERMISSION1')"])