Spring Security 权限管理原理
1.简介
授权是更具系统提前设置好的规则,给用户分配可以访问某一资源的权限,用户根据自己所具有的权限,去执行相应的操作,spring security 提供的权限管理功能主要有两种:
基于过滤器的权限管理功能(FilterSecurityInterceptor)
基于 AOP 的权限管理功能(MethodSecurityInterceptor)
2. 核心概念
2.1 角色与权限
用户信息都保存在 Authentication 信息中,Authentication 对象中有一个 Collection<? extends GrantedAuthority> getAuthorities() 当需要进行鉴权时,就会调用该方法获取用户权限,进而做出判断。无论用户采取何种认证方式,都不影响授权。
从设计层面来讲,角色和权限是两个完全不同的东西,权限是一些具体操作,例如 read、write,角色则是某些权限的集合,例如管理员、普通用户。
从代码层面讲,角色和权限并没有太大的不同。
至于 Collection<? extends GrantedAuthority> getAuthorities() 的返回值,需要分情况对待:
(1) 如果权限系统设计的比较简单,用户<==>权限<==>资源三者之间的关系,那么 getAuthorities 就是返回用户的权限
(2) 如果权限系统设计的比较复杂,如用户<==>角色<==>权限<==>资源,此时将 getAuthorities 的返回值当作权限来理解。由于 Spring Security 并未提供相关的角色类,因此此时需要我们自定义角色类。
角色继承自 GrantedAuthority,一个角色对应多个权限,然后在定义用户类的时候,将角色转为权限即可.
2.2 角色继承
指角色存在一个上下级关系,例如 ADMIN 继承自 USER,那么 ADMIN 就自动具备 USER 的所有权限。
2.3 FilterSecurityInterceptor 处理器
基于过滤器的权限过滤器(FilterSecurityInterceptor)有一个前置过滤器和后置过滤器,首先由前置处理器判断发起当前请求的用户是否具备相应的权限,如果具备则请求继续向下走,到达目标方法并执行完毕。在相应时,会经过 FilterSecurityInterceptor,次吃由后置处理器再去完成收尾工作(后置过滤器一般不工作),如图 2-3 所示。
图 2-3
2.4 前置过滤器
前置过滤器主要有两个核心组件,分别是投票器和决策器。
2.4.1 投票器
当投票器在投票时,需要两方面的权限:其一是当前用户具备哪些权限;其二是当前访问的 URL 需要哪些权限才能访问,投票器就是对这两种权限进行比较。其接口如下:
AccessDecisionVoter 常用的实现类如下图 2-4-1 所示,本项目中主要用到 RoleVoter 和 RoleHierarchyVoter。
RoleVoter:RoleVoter 是根据登陆主体的角色进行投票,即判断当前用户是否具备受保护对象所需要的角色。需要注意的是,默认情况下,角色需要以 ROLE_开始,否则 supports 方法会直接返回 false。
RoleHierarchyVoter:继承自 RoleVoter,投票逻辑和 RoleVoter 一样,不同的是 RoleHierarchyVoter 支持角色的继承,它通过 RoleHierarchyImpl 对象对用户所具有的角色进行解析,获得用户真正可触达的角色,而 RoleVoter 则直接调用 authentication.getAuthorities()方法获得用户的角色。
图 2-4-1
2.4.2 决策器
决策器由 AccessDecisionManager 负责,AccessDecisionManager 会同时管理多个投票器,由 AccessDecisionManager 调用投票器进行投票,然后根据投票结果做出相应的决策。
decide 方法:是核心的决策方法,在这个方法中判断是否允许当前 URL 调用, 如果拒绝访问的话会抛出 AccessDeniedException 异常。
supports(ConfigAttribute) 方法:用来判断是否支持 ConfigAttribute 对象。
supports(Class)方法:用来判断是否支持当前安全对象。
和决策器相关的类关系,如图 2-4-2 所示,AccessDecisionManager 会同时管理多个投票器,由 AccessDecisionManager 调用投票器进行投票,然后根据投票结果做出相应的决策,有一个抽象实现类 AbstractAccessDecisionManager,AbstractAccessDecisionManager 一共有三个子类:
AffirmativeBased:一票通过机制(默认即此)
ConsensusBased:少数服从多数机制,平局的话,则看 allowIfEqualGrantedDeniedDecisions 参数的取值
UnanimousBased:一票否决制
图 2-4-2
2.5 权限元数据
2.5.1 ConfigAttribute
在介绍投票器的时候,在具体的投票方法 vote 中,受保护的对象所需要的权限保存在一个 Collection 集合中,集合中的对象是 ConfigAttribute 而不是 GrantedAuthority,ConfigAttribute 用来存储与安全系统相关的配置属性,也就是系统关于权限的配置,接口如下:
只有一个 getAttribute 方法返回具体的权限字符串,而 GrantedAuthority 则是通过 getAuthority 方法返回用户所具有的权限,随着两个类不同,但是二者的返回值都是字符串是可以比较的。其部分实现类如图 2-5-1 所示。
图 2-5-1
2.5.2 SecurityMetadataSource
提供受保护的对象所需的权限,例如,用户访问了一个 URL 地址需要哪些权限才能访问?这个就由 SecurityMetadataSource 提供
版权声明: 本文为 InfoQ 作者【@下一站】的原创文章。
原文链接:【http://xie.infoq.cn/article/99eef4f55ce8f274e3676905f】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论