Shiro+JWT 实现权限管理(一)--Shiro
在之前的文章《权限框架Apache Shiro 和 Spring Security》中有介绍一些权限框架,当时觉得Shiro功能比较强大,也比较适合管理后台不同粒度的权限控制.
再后来的工作过程中,发现了shiro的一些不足之处--对于多端登录支持不是很友好,需要自己去实现具体功能.
经过搜索、研究发现一个新东西--JWT (JAVA WEB TOKEN),为了在网络应用环境声明而执行的一种基于 JSON 的开放标准.这玩意特别适用于分布式站点的单点登录.至于为什么选用Token,可以看下这篇文章《shiro使用(使用token预热,为什么要使用token)》
在大致研究了JWT功能后,决定对之前写的权限管理做一些优化--使用JWT做认证,配合Shrio强大的授权功能,实现更加全面、轻量化的权限管理.
之前那篇文章只写了各框架的对比,并没有详细的介绍.正好写篇文章介绍一下Shiro .But 该文只做概念介绍后面再做贴出代码吧.
Shiro
官方文档地址:http://shiro.apache.org/architecture.html
Shiro核心架构概念
介绍一下shiro需要关注的几个概念
SecurityManager shiro框架的核心 shiro通过securityManager来管理内部主键实例,并通过它来提供安全管理的各种服务.
Subject 当前操作用户--请求主体 在程序中任何地方都可以使用SecurityUtils.getSubjcet()获取当前的subject 然后利用subject.getPrincipal()获取principal--subject的标示,程序通过principal来识别唯一用户,可以是定义的toekn,也可以是用户id等.
Realms 充当shiro与应用安全数据间的桥梁和连接器,当对用户执行认证和授权验证时,shiro会从应用配置的realm中查找用户及其权限信息. 当有多个realm存在时,shiro在做用户校验的时候会按照决策来决定认证是否通过.一个realm对应一个matcher用来做用户提交认证信息和realm获取的用户信息做对比.
Shiro的功能架构图
Authentication(认证), Authorization(授权), Session Management(会话管理), Cryptography(加密)被称之为应用安全的四大基石。
Authentication 用户身份识别、判断 解决--我是我
Authorization 访问权限控制 解决--我能做什么
Session Management 会话管理 支持特异性的管理
Cryptography 对数据源进行加密同时保证轻易访问
还有其他的功能支持不同应用环境下的权限安全控制,可以根据特异需求进行丰富和加强.
shiro认证与授权
参考 https://www.jianshu.com/p/504af828a3ab
认证流程
- 调用Subject.login(token)进行登录,其会自动委托给Security Manager,调用之前必须通过SecurityUtils. setSecurityManager()设置;
- SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;
- Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实现;
- Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证;
- Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。
授权流程
- 首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer;
- Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver把字符串转换成相应的Permission实例;
- 在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;
- Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否则返回false表示授权失败。