如何用 Shiro 搭建一个基于 Token 的权限校验系统?
Shiro的架构
Authentication
:身份验证,检测用户的账号密码是否正确Authorization
:权限验证,验证用户是否有某一个角色/权限
Shiro的组件
SecurityManager
:安全管理器,即所有跟安全有关的操作都会与SecurityManager
交互。且它管理者所有Subject
。它是 Shiro 的核心Subject
:主体,代表了当前的“用户”,所有Subject
都绑定到SecurityManager
Realm
:Shiro 从Realm
中获取安全数据(如用户、角色、权限),就是说SecurityManager
如果要验证用户的身份或者角色/权限,那么它需要从Realm
中获取相应用户进行校验。可以把Realm
看成是 DataSource。Reaml
需要由用户自己实现
用 Shiro 搭建一个基于 Token 的权限校验系统
身份令牌
身份验证,即在应用中谁能证明他就是他的本人。在我们搭建的基于 Token 的认证系统当中,身份验证标识当然是根据一定规则生成的 Token 了。我们定义 OAuth2Token
,让它实现 org.apache.shiro.authc.AuthenticationToken
接口
接口提供了两个方法
1 | public interface AuthenticationToken extends Serializable { |
Shiro 有一个默认的接口实现 UsernamePasswordToken
,它将用户名当做是标识属性,密码当做是凭证
1 | public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken { |
现在我们要实现的是基于 Token 的校验,自定义的 AuthenticationToken
实现如下
1 | package io.renren.modules.sys.oauth2; |
自定义 Reaml
Realm
用来提供安全数据源,即校验用户身份验证是否通过,以及提供该用户相应的角色和权限的数据。注意,校验用户是否有正确的权限不是有 Realm
来处理,Realm
是负责提供数据,而交给 SecurityManager
来处理
自定义一个继承 org.apache.shiro.realm.AuthorizingRealm
的类,并重写 doGetAuthorizationInfo
和 doGetAuthenticationInfo
方法。还要重写 supports
方法,该方法的返回值(True、False)表明是否支持处理传入的 AuthenticationToken
类型的令牌
1 | package io.renren.modules.sys.oauth2; |
自定义 Filter
1 | package io.renren.modules.sys.oauth2; |
与 SpringBoot 集成
1 | package io.renren.config; |
使用
API接口权限控制
1 | package io.renren.modules.sys.controller; |
通过 @RequiresPermissions("sys:log:list")
来校验用户是否有权限调用这个接口
捕捉Shiro的异常
在全局异常处理器中进行处理
1 | package io.renren.common.exception; |