shiro教程1(HelloWorld)

shiro简介

官网
在这里插入图片描述

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

框架图说明

官网架构说明

从外部查看shiro框架

在这里插入图片描述>应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject

api 说明
Subject 主体,代表当前'用户'。这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者
Shiro SecurityManager 安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,可以把它看成DispatcherServlet前端控制器
Realm ,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

内部结构框架

在这里插入图片描述

组件 说明
Subject 主体,可以看到主体可以是任何可以与应用交互的“用户”;
SecurityManager 相当于SpringMVC中的DispatcherServlet或者Struts2中的FilterDispatcher;是Shiro的心脏;所有具体的交互都通过SecurityManager进行控制;它管理着所有Subject、且负责进行认证和授权、及会话、缓存的管理。
Authenticator 认证器,负责主体认证的,这是一个扩展点,如果用户觉得Shiro默认的不好,可以自定义实现;其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了;
Authrizer 授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;
Realm 可以有1个或多个Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是JDBC实现,也可以是LDAP实现,或者内存实现等等;由用户提供;注意:Shiro不知道你的用户/权限存储在哪及以何种格式存储;所以我们一般在应用中都需要实现自己的Realm;
SessionManager 如果写过Servlet就应该知道Session的概念,Session呢需要有人去管理它的生命周期,这个组件就是SessionManager;而Shiro并不仅仅可以用在Web环境,也可以用在如普通的JavaSE环境、EJB等环境;所有呢,Shiro就抽象了一个自己的Session来管理主体与应用之间交互的数据;这样的话,比如我们在Web环境用,刚开始是一台Web服务器;接着又上了台EJB服务器;这时想把两台服务器的会话数据放到一个地方,这个时候就可以实现自己的分布式会话(如把数据放到Memcached服务器);
SessionDAO DAO大家都用过,数据访问对象,用于会话的CRUD,比如我们想把Session保存到数据库,那么可以实现自己的SessionDAO,通过如JDBC写到数据库;比如想把Session放到Memcached中,可以实现自己的Memcached SessionDAO;另外SessionDAO中可以使用Cache进行缓存,以提高性能;
CacheManager 缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能
Cryptography 密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密的。

常见单词说明

单词 说明
Subject 主体
Security 完全
Realm 领域、范围
Autherticator 认证器
Authentication 认证
Authorizer 授权器
Authorization 授权
Cryptography 密码、加密
Credential 证书、凭证 密码
Matcher 匹配器
Principal 身份

Shiro中的shiro.ini说明

shiro.ini放置在classpath路径下shiro会自动查找。
ini配置文件中有四大主要配置类
main users roles urls

main

提供了对根对象securityManager及其依赖对象的配置

#创建对象
securityManager=org.apache.shiro.mgt.DefaultSecurityManager 

其构造器必须是public空参构造器,通过反射创建相应的实例。
1、对象名=全限定类名 相对于调用public无参构造器创建对象
2、对象名.属性名=值 相当于调用setter方法设置常量值
3、对象名.属性名=$对象引用 相当于调用setter方法设置对象引用

users

提供了对用户/密码及其角色的配置,用户名=密码,角色1,角色2

username=password,role1,role2
例如:
配置用户名/密码及其角色,格式:“用户名=密码,角色1,角色2”,角色部分可省略。如:

[users] 
zhang=123,role1,role2 
wang=123 

roles

提供了角色及权限之间关系的配置,角色=权限1,权限2

role1=permission1,permission2
例如:
配置角色及权限之间的关系,格式:“角色=权限1,权限2”;如:

[roles] 
role1=user:create,user:update 
role2=*  

如果只有角色没有对应的权限,可以不配roles

urls

用于web,提供了对web url拦截相关的配置,url=拦截器[参数],拦截器

/index.html = anon 
/admin/** = authc, roles[admin],perms["permission1"]

第一个案例

官方教程

添加对应的依赖

<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-core</artifactId>
	<version>1.1.0</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-simple</artifactId>
	<version>1.6.1</version>
	<scope>test</scope>
</dependency>

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>commons-logging</groupId>
	<artifactId>commons-logging</artifactId>
	<version>1.2</version>
</dependency>

添加shiro.ini文件

src/main/resource下添加
在这里插入图片描述
添加内容如下

[users]
root = 123456
# 账号为root 密码是 123456

认证操作

@Test
public void test() {
	// 1.获取SecurityManager工厂对象
	Factory<SecurityManager> factory = 
			new IniSecurityManagerFactory("classpath:shiro.ini");
	// 2.通过Factory对象获取SecurityManager对象
	SecurityManager securityManager = factory.getInstance();
	// 3.将SecurityManager对象添加到当前运行环境中
	SecurityUtils.setSecurityManager(securityManager);
	
	// 4.获取Subject对象
	Subject subject = SecurityUtils.getSubject();
	AuthenticationToken token = new UsernamePasswordToken("root", "123456");
	// 登录操作
	subject.login(token);
	// 获取登录的状态
	System.out.println(subject.isAuthenticated());
}

测试

账号密码正确

在这里插入图片描述

账号错误

在这里插入图片描述账号错误抛 UnknownAccountException异常

密码错误

在这里插入图片描述
密码错误会抛 IncorrectCredentialsException异常

所以代码可以调整下:

	@Test
	public void test() {
		// 1.获取SecurityManager工厂对象
		Factory<SecurityManager> factory = 
				new IniSecurityManagerFactory("classpath:shiro.ini");
		// 2.通过Factory对象获取SecurityManager对象
		SecurityManager securityManager = factory.getInstance();
		// 3.将SecurityManager对象添加到当前运行环境中
		SecurityUtils.setSecurityManager(securityManager);
		
		// 4.获取Subject对象
		Subject subject = SecurityUtils.getSubject();
		AuthenticationToken token = new UsernamePasswordToken("root", "111");
		// 登录操作
		try {
			subject.login(token);
		} catch (UnknownAccountException e) {
			System.out.println("账号出错...");
		} catch(IncorrectCredentialsException e){
			System.out.println("密码出错...");
		}
		// 获取登录的状态
		System.out.println(subject.isAuthenticated());
	}

认证流程总结

login方法

在这里插入图片描述

DelegatingSubject中的login方法

在这里插入图片描述

在此方法中我们看到是 SecurityManager来管理认证操作的
继续进入

进入DefaultSecurityManager的login方法

在这里插入图片描述

此方法中调用Authenticator认证

在这里插入图片描述

AbstractAuthenticator认证

在这里插入图片描述

ModularRealmAuthenticator

在这里插入图片描述

在该方法中获取ini文件中的信息,加载解析不是在次方法中。

在这里插入图片描述

AuthenticatingRealm

在这里插入图片描述

流程描述

1、创建token令牌,token中有用户提交的认证信息即账号和密码
2、执行subject.login(token),最终由securityManager通过Authenticator进行认证
3、Authenticator的实现ModularRealmAuthenticator调用realm从ini配置文件取用户真实的账号和密码,这里使用的是IniRealm(shiro自带)
4、IniRealm先根据token中的账号去ini中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。

原文地址:https://www.cnblogs.com/dengpengbo/p/10316277.html