如何用 Shiro 搭建一个基于 Token 的权限校验系统?
Shiro的架构
Authentication:身份验证,检测用户的账号密码是否正确Authorization:权限验证,验证用户是否有某一个角色/权限
Shiro的组件
SecurityManager:安全管理器,即所有跟安全有关的操作都会与SecurityManager交互。且它管理者所有Subject。它是 Shiro 的核心Subject:主体,代表了当前的“用户”,所有Subject都绑定到SecurityManagerRealm: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; |