在 Spring Security 中分离角色和权限

介绍

分离角色和权限的目的是避免在代码中嵌入安全策略决策。此类决策应在运行时设置,因为它们因客户而异,随时间而变化,有时需要立即更改(例如,响应安全漏洞)。

例子

例如,考虑以下规则之间的区别:
[code lang=”java”]@PreAuthorize(
"hasAnyRole('ROLE_STUDENT', 'ROLE_FACULTY_MEMBER', 'ROLE_ADMIN')")
public Forum getForum(long id){ ... }[ /code]
还有这个:
[code lang=”java”]@PreAuthorize("hasRole('PERM_READ_FORUMS')")
public Forum getForum(long id) { ... }[/code]
当有人决定教助理、家长、教师培训师、认证人或任何数量的其他角色应该获得访问权限,或者其中一个角色应该失去访问权限(例如,仅限教师的论坛)。使用该软件的不同客户的角色可能不同,并且许多角色甚至可能对某些客户没有任何意义。

面对这种变化,第二条规则更有弹性,因为它本质上说,如果用户通常具有对论坛的阅读访问权限,则他可以获得给定的论坛。该规则并不完美——我们可能会决定不存在“一般论坛的阅读权限”之类的东西(也就是说,访问权限存在于逐个论坛的基础上)——但显然它更加灵活,尤其是如果我们可以在代码本身之外建立角色和权限之间的关系。我们当然可以做到。

因此,作为一般规则,与基于角色的规则相比,更喜欢基于权限的规则。这条规则有例外,但它作为一般规则成立。

Spring Security 3 在以上述方式分离角色和权限的问题上显得精神分裂。ROLE_STUDENT、PERM_READ_FORUMS 等的底层接口称为 GrantedAuthority,这听起来像是“权限”而不是“角色”的一种奇特方式。但是 Spring Security 参考文档中的示例倾向于将授予的权限视为角色,甚至 hasRole() 和 hasAnyRole() 谓词也引导我们直接使用角色,由于已经给出的原因,这充其量是一个值得怀疑的做法。

 

图 1 将角色与权限分开的用户模式。

抛开明显的精神分裂症不谈,Spring Security 让做正确的事情变得容易。例如,示例代码使用图 1.2 中的 user/role/permission 模式支持的自定义 UserDetailsS​​ervice sip07-schema-mysql.sql 脚本(可在此处获得)包含此模式,但这只是一个示例。即使您使用的是 JdbcDaoImpl 而不是自定义的 UserDetailsS​​ervice,您也可以利用 Spring Security 组模式来分离角色和权限。

除了模式之外,我们还需要一些示例数据,以便我们可以实际测试安全配置。图 2 显示了我们的每个示例用户所拥有的角色和权限,这些角色和权限包含在 sip07-data-mysql.sql 脚本中。

 

图 2 示例应用程序的用户、角色和权限

这就是我们的源代码更改。现在我们需要“激活”安全注释。为此,我们在 beans-security.xml 配置中添加一行:
[code lang=”java”]<global-method-security pre-post-annotations="enabled" />[/code]
我们已经启用 Spring Security 的前注和后注,默认禁用,因为它们允许我们使用 SpEL 以优雅的方式定义访问规则。这是 Spring Security 3 中的首选方法。但是,为了完整起见,我们列出了其他几个选项:

  • jsr250-annotations=”enabled”:激活标准的 JSR 250 安全注解。尽管这些是标准的,但它们只支持简单的基于角色的规则,并且不如 Spring Security 的 pre/post 注释那么强大。这些默认情况下被禁用。
  • secure-annotations=”enabled”:支持 Spring 遗留的 @Secured 注解。最初被 JSR 250 @RolesAllowed 注解取代,现在被 Spring Security @PreAuthorize 注解取代。@Secured 默认禁用。

那是基于注释的配置。要试用安全注释,请尝试以下操作:

  • 启动应用程序并单击论坛链接。Spring Security 将强制登录,因为对 getForums() 的调用需要 PERM_READ_FORUMS 权限。
  • 以用户 daniel/p@ssword 登录。他只有学生角色。
  • 进入其中一个论坛并尝试阻止消息。您应该在对话框中收到一条错误消息,因为 ForumServiceImpl.setMessageVisible() 方法需要 PERM_ADMIN_MESSAGES 权限,而学生角色没有该权限。
  • 尝试编辑和删除消息。您将能够获得编辑页面和删除确认框,但是当您尝试实际保存编辑或确认删除时会出现错误消息,因为学生角色没有所需的PERM_UPDATE_MESSAGES和PERM_DELETE_MESSAGES权限.
  • 注销,然后在 juan/p@ssword 下重新登录。用户 juan 具有管理员角色。尝试相同的操作。您应该能够执行所有这些,因为管理员角色具有所需的权限。

概括

我们创建了授权规则并将它们应用于 Java 方法。我们向您展示了为什么我们使用 hasRole() 谓词来检查权限,因为角色和权限不是一回事。一个角色通常需要一组权限。例如,发布工程师角色可能有权将软件包部署到服务器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值