Shiro视频教程

项目需求

用户登陆

一般情况下,有用户交互的系统基本都有用户登陆的功能,用户需要输入账号和密码进行登陆,如果用户没有登陆则无法使用一些功能,比如:我的中心、我已购买的订单等。

权限控制

一般情况下,一个系统有若干类用户来使用,不同类的用户允许使用的功能不一样,比如:系统管理员用户可以登陆系统后台,查询系统的操作日志、系统数据备份等;普通业务员用户可以使用系统的一些业务功能,比如:商品管理、统计分析等。当用户登陆系统后去使用系统功能的时候,系统会进行权限控制,有此功能操作权限的用户方可使用此功能,没有此功能操作权限的用户则无法使用,比如:张三是个系统管理员,他拥有了“查询系统日志”功能的权限,所以他可以正常使用“查询系统日志”的功能,他无法使用“统计分析”的功能,因为他没有“统计分析”功能的操作权限。

解决方案分析

认证和授权的基本概念

以上的功能需求在很多项目中都存在,它们涉及到两个概念,即认证和授权,下面先介绍下认证和授权的基本概念。

什么是认证授权

基本上涉及到用户参与的系统都要进行认证授权,认证授权属于系统安全的范畴,它实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。

认证授权包括用户身份认证和授权两部分,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。

什么是认证

认证即用户身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。对于采用指纹等系统,则出示指纹;对于硬件等刷卡系统,则需要刷卡。

一个b/s系统认证的基本流程如下:
在这里插入图片描述
名词解释:
系统资源:系统的URL、系统菜单、系统页面、系统中的数据等。
公开地址:无需认证即可访问的地址。

什么是授权

授权,即访问控制,控制用户能访问哪些资源。首先系统会给用户分配权限,如果用户拥有了某个系统资源的访问权限则用户可以正常文章,否则则拒绝访问。
如下流程:
在这里插入图片描述

认证的解决方案

用户名密码认证流程

系统的认证方式有多种,比如:输入账号和密码方式,证书方式,指纹方式等,这里讲解用户名密码方式的认流程,如下图:
在这里插入图片描述

过虑器或拦截实现

使用拦截器或过虑器可以实现用户认证,思路如下:
1、创建过虑器或拦截器,配置拦截用户请求的url
2、过虑器或拦截器中获取session,从session中获取当前登陆的用户,如果获取到则放行,否则跳转到登陆页面

使用认证框架实现

认证功能属于通用的功能,完全可以使用框架统一处理,常见的认证框架有很多,比如:Shiro、Spring Security、OAuth等,框架会将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,授权、加密、会话管理等功能,组成了一个通用的安全认证框架。

技术选型

推荐使用框架实现用户认证的功能,因为框架已将用户认证的常见功能全部实现,我们只需要按照框架的要求进行开发,大大提交生产效率。

本系统选用Shiro框架,Shiro框架是一个轻量级的认证框架,不仅功能强大而且使用简单,Shiro框架支持C/S系统、B/S系统、分布式架构系统的认证,并且Shiro框架与Spring框架整合也较好。

关键对象

上边的流程图中需要理解以下关键对象:

 Subject:主体
访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;

 Principal:身份信息
是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。

 credential:凭证信息
是只有主体自己知道的安全信息,如密码、证书等。

认证实现方案

使用认证框架实现

认证功能属于通用的功能,完全可以框架统一处理,Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。

为什么用框架

既然shiro将安全认证相关的功能抽取出来组成一个框架,使用shiro就可以非常快速的完成认证、授权等功能的开发,降低系统成本。

shiro使用广泛,是apache的开源项目,shiro可以运行在web应用,非web应用,集群分布式应用中越来越多的用户开始使用shiro。

java领域中spring security(原名Acegi)也是一个开源的权限管理框架,但是spring security依赖spring运行,而shiro就相对独立,最主要是因为shiro使用简单、灵活,所以现在越来越多的用户选择shiro。

shiro认证入门

Shiro介绍

Shiro是Apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。

Shiro使用广泛,Shiro可以应用在C/S应用,B/S应用、集群分布式应用中,越来越多的用户开始使用shiro。

如下图是Shiro的框架图:
在这里插入图片描述

Subject

Subject即主体,外部应用与subject进行交互,subject记录了当前操作用户,将用户的概念理解为当前操作的主体,可能是一个通过浏览器请求的用户,也可能是一个运行的程序。

SecurityManager

SecurityManager即安全管理器,对全部的subject进行安全管理要进行认证和授权,它是shiro的核心,负责对所有的subject进行安全管理。通过SecurityManager可以完成subject的认证、授权等,实质上SecurityManager是通过Authenticator进行认证,通过Authorizer进行授权,通过SessionManager进行会话管理等。

Authenticator

Authenticator即认证器,对用户身份进行认证,Authenticator是一个接口,shiro提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数需求,也可以自定义认证器。

Authorizer

Authorizer即授权器,用户通过认证器认证通过,在访问功能时需要通过授权器判断用户是否有此功能的操作权限。

realm(重点)

Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户身份信息及用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息。

注意:不要把realm理解成只是从数据源取数据,在realm中还有认证授权校验的相关的代码。

sessionManager

sessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。

SessionDAO

SessionDAO即会话dao,是对session会话操作的一套接口,比如要将session存储到数据库,可以通过jdbc将会话存储到数据库。

CacheManager

CacheManager即缓存管理,将用户权限数据存储在缓存,这样可以提高性能。

Cryptography

Cryptography即密码管理,shiro提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。

认证流程

在这里插入图片描述
1、构造SecurityManager环境
SecurityManager是Shiro框架的核心,SecurityManager负责认证和授权等核心功能,它包括了Authenticator认证器、Authorizer授权器。
2、Subject,主体即用户,
在Shiro中subject是一个接口,面向程序员的接口,程序员使用Subject接口执行认证操作。
调用subject.login(token)执行认证。
Token是令牌,令牌中包括账号和密码。
3、外部程序通过Subject 的login方法进行认证,shiro框架交由SecurityManager进行认证,调用SecuityManager的login方法
4、SecurityManager执行Login方法最终通过Authenticator认证器去执行认证。
5、Authenticator认证器去认证时候会调用Realm从用户账号及正确的密码。

入门程序

通过入门程序我们去理解Shiro几个核心组件的作用及认证流程。

加入shiro的jar包

与其它java开源框架类似,将shiro的jar包加入项目就可以使用shiro提供的功能了。shiro-core是核心包必须选用,还提供了与web整合的shiro-web、与spring整合的shiro-spring。

在工程加入下边依赖:

<dependency>
				<groupId>org.apache.shiro</groupId>
				<artifactId>shiro-core</artifactId>
				<version>1.2.3</version>
			</dependency>
			<dependency>
				<groupId>org.apache.shiro</groupId>
				<artifactId>shiro-web</artifactId>
				<version>1.2.3</version>
			</dependency>
			<dependency>
				<groupId>org.apache.shiro</groupId>
				<artifactId>shiro-spring</artifactId>
				<version>1.2.3</version>
			</dependency>
			<dependency>
				<groupId>org.apache.shiro</groupId>
				<artifactId>shiro-ehcache</artifactId>
				<version>1.2.3</version>
			</dependency>

shiro-token.ini

通过Shiro-token.ini配置文件初始化SecurityManager环境。

在eclipse配置后,在classpath创建shiro.ini配置文件,为了方便测试将用户名和密码配置的shiro.ini配置文件中:

[users]
zhang=123
lisi=123

认证代码

// 用户登陆、用户退出


@Test
	public void testLoginAndLogout() {

		// 构建SecurityManager工厂,IniSecurityManagerFactory可以从ini文件中初始化SecurityManager环境
		Factory<SecurityManager> factory = newIniSecurityManagerFactory(
				"classpath:shiro.ini");

		// 通过工厂创建SecurityManager
		SecurityManagersecurityManager = factory.getInstance();
		
		// 将securityManager设置到运行环境中
		SecurityUtils.setSecurityManager(securityManager);

		// 创建一个Subject实例,该实例认证要使用上边创建的securityManager进行
		Subject subject = SecurityUtils.getSubject();

		// 创建token令牌,记录用户认证的身份和凭证即账号和密码
		UsernamePasswordToken token = newUsernamePasswordToken("zhang", "123");

		try {
			// 用户登陆
			subject.login(token);
		} catch (AuthenticationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 用户认证状态

		Boolean isAuthenticated = subject.isAuthenticated();

		System.out.println("用户认证状态:" + isAuthenticated);

		// 用户退出

		subject.logout();

		isAuthenticated = subject.isAuthenticated();

		System.out.println("用户认证状态:" + isAuthenticated);

	}

认证的执行流程

在这里插入图片描述
1、 创建token令牌,token中有用户输入的认证信息即账号和密码
2、 执行subject.login(token)
3、 执行subject.login(token)会调用securityManager.login(token)方法。
4、 调用securityManager.login(token)方法最终通过Authenticator进行认证
5、 Authenticator认证器的实现类为ModularRealmAuthenticator,它调用realm(IniRealm)从ini配置文件取用户真实的账号和密码, IniRealm是Shiro自带的realm。
6、 IniRealm先根据token中的账号(token中的账号即用户输入的账号)去ini文件中找该账号是否
7、 如果找不到则给ModularRealmAuthenticator返回null,最终抛出UnknownAccountException异常。
8、 如果IniRealm找到账号则会获取ini文件中账号所对应的密码。
9、 IniRealm调用凭证匹配器去比较Token中的密码和Ini文件中的密码是否一致。
10、 如果Token中的密码和Ini文件中的密码不一致则ModularRealmAuthenticator最终抛出异常IncorrectCredentialsException。
11、 如果匹配密码一致则认证通过。

总结

通过入门程序我们了解了shiro框架几个组件的功能,如下:
Subject:Subject在Shiro中是一个接口,接口中定义了很多认证和授权相关的方法,外部程序通过subject进行认证授,而subject是通过SecurityManager安全管理器进行认证授权。

SecurityManager:安全管理器,SecurityManager是一个接口,继承了Authenticator(认证器), Authorizer(授权器), SessionManager这三个接口。

Authenticator:即认证器,对用户身份进行认证,Authenticator是一个接口,shiro提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数。

Realm:即领域,相当于DataSource数据源,入门程序中用的IniReallm是Shiro框架提供的,它的功能是从ini文件中读取数据,在实际使用时一般都需要自定义realm从数据库来读取用户的账号和密码。

自定义Realm

上边的程序使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。

shiro提供的realm

在这里插入图片描述
最基础的是Realm接口,CachingRealm负责缓存处理,AuthenticationRealm负责认证,AuthorizingRealm负责授权,通常自定义的realm继承AuthorizingRealm。

自定义Realm

自定义一个realm如下:

package com.pbteach.shiro;

public class CustomRealm1 extendsAuthorizingRealm {

	@Override
	public String getName() {
		return"customRealm1";
	}

	//支持UsernamePasswordToken
	@Override
	publicboolean supports(AuthenticationToken token) {
		return token instanceofUsernamePasswordToken;
	}

	//认证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throwsAuthenticationException {
		
		//从token中获取用户身份信息
		String username = (String) token.getPrincipal();
		//拿username从数据库中查询
		//....
		//如果查询不到则返回null
		if(!username.equals("zhang")){//这里模拟查询不到
			returnnull;
		}
		
		//获取从数据库查询出来的用户密码
		String password = "123";//这里使用静态数据模拟。。
		
		//返回认证信息由父类AuthenticatingRealm进行认证
		SimpleAuthenticationInfosimpleAuthenticationInfo = newSimpleAuthenticationInfo(
				username, password, getName());

		returnsimpleAuthenticationInfo;
	}

	//授权
	@Override
	protectedAuthorizationInfodoGetAuthorizationInfo(
			PrincipalCollection principals) {
		// TODO Auto-generated method stub
		returnnull;
	}

}

shiro-realm.ini

[main]
#自定义 realm
customRealm=com.pbteach.shiro.authentication.realm.CustomRealm1
#将realm设置到securityManager
securityManager.realms=$customRealm

思考:这里为什么不用配置[users]了??

测试代码

测试代码同入门程序,将ini文件的地址修改为shiro-realm.ini。

分别模拟账号不存在、密码错误、账号和密码正确进行测试。

自定义realm执行流程

自定义Realm的执行流程和第一个入门程序基本一致,只需要将IniRealm换成自定义的CustomRealm1即可,如下图:
在这里插入图片描述

1、 创建token令牌,token中有用户输入的认证信息即账号和密码
2、 执行subject.login(token)
3、 执行subject.login(token)会调用securityManager.login(token)方法。
4、 调用securityManager.login(token)方法最终通过Authenticator进行认证
5、 Authenticator认证器的实现类为ModularRealmAuthenticator,它调用CustomRealm1的doGetAuthenticationInfo方法。
6、 doGetAuthenticationInfo方法查询账号是否存在,实际程序会从数据库中查询账号是否存在。
7、 如果找不到CustomRealm1则给ModularRealmAuthenticator返回null,最终抛出UnknownAccountException异常。
8、 如果CustomRealm1找到账号则会查询账号所对应的密码,实际程序中会也数据库中查询账号对应的正确密码。
9、 CustomRealm1调用凭证匹配器去比较Token中的密码和正确的密码是否一致。
10、 如果Token中的密码和正确密码不一致则ModularRealmAuthenticator最终抛出异常IncorrectCredentialsException。
11、 如果匹配密码一致则认证通过。

深入学习

系列讲义:

http://www.pbteach.com/post/java_distribut/auth_shiro_01/

http://www.pbteach.com/post/java_distribut/auth_shiro_02/

视频教程:

http://www.pbteach.com/post/java_distribut/auth_shiro/

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页