shiro
一、认识Shiro
-
什么是shiro?
shiro是一个基于java的开源的安全管理框架,可以完成认证、授权、会话管理、加密、缓存等功能。
-
为什么学习shiro?
在java的世界中,安全管理框架有
spring security
和shiro
。spring security
要依赖于spring,并且比较复杂。shiro比较简单且比较独立,既可以在Java SE
中使用,也可以在Java EE
中使用,并且在分布式集群环境下也可以使用。 -
Shiro
的结构体系:Authentication:认证
验证用户是否合法,也就是登陆。
Authorization:授权
授予访问访问某些资源的权限。
Session Management:会话管理
用户登陆后的用户信息通过
Session Management
来进行管理,不管在什么应用中。Crytography:加密
提供了常见的一些加密算法,使得在应用中可以很方便的实现数据安全。并且使用很便捷。
Web Support:
Web
应用程序支持
Shiro
可以很方便的集成到web应用程序中。Caching:缓存
Shiro
提供了对缓存的支持,支持多种缓存架构;如:ehcache,还支持缓存数据库,如:Redis
。Concurrency:并发支持
支持多线程并发访问。
Testing:测试
Run As:允许用户假设为另一个用户进行登陆。
Remember me:记住我。
-
Shiro
架构:subject
主体,可以是用户,也可以是第三方程序等,可以用于获取主体信息,Principals和Credentials
。Security Manager
安全管理器 安全管理器是
Shiro
架构的核心。由其来协调管理Shiro
各个组件之间的工作。Authenticator
:认证器 负责验证用户的身份
Authorizer
:授权器 负责为合法的用户指定其权限。控制用户可以访问哪些资源。
Realms
域 用户通过
Shiro
来完成相关的安全工作,Shiro是不会去维护数据信息的。在Shiro的工作过程中,数据的查询和获取工作是通过Realm
从不同的数据源来获取的。Realm
可以获取数据库信息,文本信息等。在Shiro
中可以有一个Realm
,也可以有多个。
用户认证
-
Authentication
用户认证 验证用户是否合法:需提供用户的身份(
Principals
)和凭证给Shiro
principals
:用户的身份信息,是subject
的标识属性。能够唯一标识subject
。如:电话号码、邮箱、身份证等。
Credentials
凭证:密码。是值被subject
知道的秘密值。可以是密码,也可以是数字证书等。 **
Principals/Credentials
**最常见的组合:用户名/密码。在Shiro
中通常使用UsernamePasswordToken
来指定身份和凭证信息。
二、HelloWord
1、pom文件
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.4.1</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
2、配置
shiro.ini
文件
[users]
dtz=123,admin
ylz=456,manager,seller
xlz=789,clerk
# --------------------------------------------------------------------------
# 角色及其权限信息
# 预定权限:user:query
# user:detail:query
# user:update
# user:insert
# user:update
# .....
[roles]
# admin 拥有所有的权限,用*标识
admin = *
# clierk 只有查询权限
clerk = user:query,user:detail:query
# manager 有user的所有权限
manager=user:*
3、代码
package com.dtz.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
public class HelloWorld {
public static void main(String[] args) {
//创建SecurityFactory,加载ini配置文件,并通过它创建SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//Shiro核心:SecurityManager
SecurityManager securityManager = factory.getInstance();
//将SecurityManager托管到SecurityUtils工具类中(ops:之后可以不必关心SecurityManager)
SecurityUtils.setSecurityManager(securityManager);
//获取主体:Subject,作用:直接由用户使用,调用功能简单,其底层调用SecurityManager的相关流程
//通过subject可以执行shiro的相关功能(身份认证或权限校验)
Subject subject = SecurityUtils.getSubject();
//身份认证(类似登陆逻辑)
//通过subject获取当前用户的登陆状态(ops:从session中同步信息)
if (!subject.isAuthenticated()) {
//判断是否登陆
//通过subject进行身份认证
UsernamePasswordToken token = new UsernamePasswordToken("ylz", "456");
try {
subject.login(token);
} catch (UnknownAccountException e) {
System.out.println(token.getPrincipal() + "用户不存在");
} catch (IncorrectCredentialsException e1) {
System.out.println(token.getPrincipal() + "密码错误");
} catch (LockedAccountException e2) {
System.out.println(token.getPrincipal() + "账户冻结");
} catch (AuthenticationException e3) {
e3.printStackTrace();
}
}
//角色验证
boolean isAdmin = subject.hasRole("admin");
System.out.println("isAdmin:" + isAdmin);
System.out.println("isManager:" + subject.hasRole("manager"));
//权限校验
System.out.println(subject.isPermitted("a:b"));
System.out.println(subject.isPermitted("user:query"));
//登出:身份信息,登陆状态信息,权限信息,角色信息,会话信息全部抹除
subject.logout();
}
}
4、权限规则
1> user:query,user:insert,order:delete,menu:show
【:】作为分隔符,分隔资源和操作【资源:操作】
【,】作为分隔符,分隔多个权限【权限1,权限2,权限3】
2> user:*, *:query
【*】作为通配符,代表所有操作,资源
【user:*】即user的所有操作
【*:query】即所有资源的查询操作
3> *
代表一切资源的一切权限 = 最高权限
4> 细节:
1)user:* 可以匹配 user:xx, user:xx:xxx
*:query 只可以匹配 xx:query,不能匹配 xx:xxx:query,除非是 * : * : query
2)user:update,user:insert 可以简写为 "user:update,insert",注意加引号
[roles]
manager1 = user:query,user:update,user:insert
manager2 = "user:query,update,insert",注意要加引号
如上manager1和manager2权限等价
subject.isPermittedAll("user:update","user:insert","user:query")
实例级权限标识:【标识:操作:实例】,粒度细化到具体某个资源实例
1> user:update:1 , user:delete:1
对用户1可以update,对用户1可以delete
2> "user:update,delete:1" 和上面等价
subject.isPermittedAll("user:update,delete:1", "user:update", "user:delete:1");
3> user:*:1 , user:update:* , user:*:
三、与web集成
与web项目集成后,Shiro的工作模式如下:
如上:ShiroFilter拦截所有请求,对于请求做访问控制
如请求对应的功能是否需要有认证身份,是否需要某种角色,是否需要某种权限
1> 如果没有做身份认证,则将请求强制跳转到登陆页面。
如果没有充分的角色或权限,则将请求跳转到权限不足的页面。
2> 如果校验成功,则执行请求的业务逻辑
pom
<dependencies>
<!-- servlet -->
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>