Shiro概述
Shiro是Java的一个安全框架,可以帮助我们完成:认证、授权、加密、会话管理、与web集成、缓存等。
Shiro的基本功能如下:
Authentication:身份认证、登陆,验证用户是不是拥有相应的身份。
Authorization:授权,即权限验证,验证某个已经登陆的用户是否拥有某个权限,eg:验证用户是否拥有某个角色。
Session Manager:会话管理,登陆后退出之前的信息都在会话中。
Cryptography:加密,保护数据的安全性。
Web Support:可以非常容易的集成到WEB环境。
Caching:缓存,存储用户登录后的信息、拥有的角色、权限不必每次都去查,提高效率。
Concurrency:Shiro支持多线程的并发验证。
Testing:提供测试支持。
Run As:允许一个用户假装为另一个用户的身份访问。
Remember Me:记住我,下次不用登陆。
Shiro的执行机制
Subject:主体,是应用程序代码直接交互的对象,所有的Subject都绑定到SecurityManager ,与Subject的所有交互都会委托给SecurityManager ,SecurityManager 才是真正的执行者。
SecurityManager :安全管理器,所有与安全有关的操作都会与SecurityManager 交互,是Shiro的核心。
Realm:域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),SecurityManager 要验证用户身份需要从Realm中获取相应的用户进行比较以确定身份是否合法,可以把Realm看出安全数据源。
可以看出:Shiro不提供维护用户/权限,而是通过R让开发人员自己注入。
Shiro 的内部架构
Subject:主体,可以是任何可以和应用交互的”用户”。
SecurityManager:是Shiro的核心。
Authenticator:认证器,负责主体认证,他需要认证策略(Authentication Strategy),即用户认证通过的情况。
Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作。
Realm:安全实体数据源,即用于获取安全实体。
SessionManager:管理主体与应用之间交互的数据。
SessionDAO:把Session保存到数据库。
CacheManager:缓存控制器,用来管理用户、角色、权限等的缓存。
Cryptography:密码模块
身份验证
在Shiro中,用户需要提供 principals (身份 eg:用户名)和 credentials(证明 eg:密码)给 shiro,从而应用能验证用户身份。
身份验证的步骤:
- 1.收集用户身份/凭证,即用户名/密码。
- 2.调用Subject.login进行登陆,如果失败将得到相应的AuthenticationException 异常。
- 3.调用Subject.logout进行退出操作。
授权
授权中的几个关键对象:
- 主体:即访问应用的用户,在Shiro 中使用Subject 代表该用户,用户只有授权后才能访问相应的资源。
- 资源:在应用中用户可以访问的任何东西。
- 权限:表示应用中用户能不能访问某个资源。
- 角色:角色代表了操作集合,可以理解为权限集合。
Shiro 支持三种方式的授权:
- 编程式:通过写 if/else 授权代码块完成:
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有权限
} else {
//无权限
}
- 注解式:通过在执行的 Java 方法上放置相应的注解完成:
@RequiresRoles("admin")
public void hello() {
//有权限
}
- JSP/GSP 标签:在 JSP/GSP 页面通过相应的标签完成:
<shiro:hasRole name="admin">
<!— 有权限 —>
</shiro:hasRole>
授权:基于角色的访问控制(隐式角色)
在 ini 配置文件配置用户拥有的角色:规则即:“用户名=密码,角色1,角色2”
[users]
zhang=123,role1,role2
wang=123,role1
授权:基于资源的访问控制(显示角色)
在 ini 配置文件配置用户拥有的角色及角色-权限关系,规则:“用户名=密码,角色 1,角色 2”“角色=权限 1,权限 2”。
[users]
zhang=123,role1,role2
wang=123,role1
[roles]
role1=user:create,user:update
role2=user:create,user:delete
字符串通配符权限
1、单个资源单个权限
subject().checkPermissions("system:user:update");
2、单个资源多个权限
role41=system:user:update,system:user:delete
判断:
subject().checkPermissions("system:user:update", "system:user:delete");
或者
role42="system:user:update,delete"
判断:
subject().checkPermissions("system:user:update,delete");
3、单个资源全部权限
ini 配置
role51="system:user:create,update,delete,view"
判断:
subject().checkPermissions("system:user:create,delete,update:view");
4、所有资源全部权限
ini 配置
role61=*:view
然后通过如下代码判断
subject().checkPermissions("user:view");
5、实例级别的权限
单个实例单个权限
ini 配置
role71=user:view:1
对资源 user 的 1 实例拥有 view 权限。
然后通过如下代码判断
subject().checkPermissions("user:view:1");
单个实例多个权限
ini 配置
role72="user:update,delete:1"
对资源 user 的 1 实例拥有 update、delete 权限。
然后通过如下代码判断
subject().checkPermissions("user:delete,update:1");
subject().checkPermissions("user:update:1", "user:delete:1");
单个实例所有权限
ini 配置
role73=user:*:1
对资源 user 的 1 实例拥有所有权限。
然后通过如下代码判断
subject().checkPermissions("user:update:1", "user:delete:1", "user:view:1");
所有实例单个权限
ini 配置
role74=user:auth:*
对资源 user 的 1 实例拥有所有权限。
然后通过如下代码判断
subject().checkPermissions("user:auth:1", "user:auth:2");
所有实例所有权限
ini 配置
role75=user:*:*
对资源 user 的 1 实例拥有所有权限。
然后通过如下代码判断
subject().checkPermissions("user:view:1", "user:auth:2");
编码/加密
Shiro 提供了 base64 和 16 进制字符串编码 / 解码。
Shiro 还提供对称式加密 / 解密算法的支持,如 AES、Blowfish 等