028-86922220

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

什么是Shiro验证

这期内容当中小编将会给大家带来有关什么是Shiro验证,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

我们提供的服务有:成都做网站、网站制作、微信公众号开发、网站优化、网站认证、上栗ssl等。为数千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的上栗网站制作公司

shiro验证:用户需要提供系统理解和信任的某种身份证明(密码、证书等),来证明自己可以登录该系统。
在验证阶段需要先理解几个术语:

如下是从官网获取的验证架构图:
什么是Shiro验证

接下来就开始使用ShiroAPI完成验证操作了。
环境准备:

本文使用 Maven 构建,因此需要一点 Maven 知识。首先准备环境依赖:


    
        junit
        junit
        4.9
        test
    
    
        commons-logging
        commons-logging
        1.2
    
    
        org.apache.shiro
        shiro-core
        1.3.2
    

添加 junit 和 shiro-core 依赖即可。

初识:登录 / 退出

1、首先准备一些用户身份 / 凭据(shiro.ini)

[users]
zhangsan=123
lisi=123

2、测试用例(com.luther.shiro.authenticator.AuthenticateTest)

/**
 * 底层默认使用ModularRealmAuthenticator验证模块(多realm验证) 
 * AtLeastOneSuccessfulStrategy验证策略(只要有一个域成功进行身份验证,  *  则认为成功。否则失败。会返回所有成功的用户标识)  * @author luther  * @time 2019年7月5日  上午9:58:39  */ @Test public void testHelloWorld() { // 使用Ini配置文件初始化SecurityManager Factory factory = new IniSecurityManagerFactory("classpath:shiro.ini"); // 得到SecurityManager实例 并绑定给SecurityUtils SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); // 得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123"); // 记住用户 token.setRememberMe(Boolean.TRUE); try { // 登录 subject.login(token); System.out.println("登录成功"); } catch (AuthenticationException e) { System.err.println("登录失败,失败原因:"); e.printStackTrace(); } assertTrue("用户已验证成功", subject.isAuthenticated()); // 退出 subject.logout(); }

Realm
realm 接口结构如下,其下方法有: 什么是Shiro验证

String getName(); //返回一个唯一的Realm名字
boolean supports(AuthenticationToken token); //判断此Realm是否支持此Token
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;  //根据Token获取认证信息

其中主要默认实现如下:
org.apache.shiro.realm.text.IniRealm:从ini文件获取用户权限等信息。
org.apache.shiro.realm.text.PropertiesRealm:从properties文件获取用户权限等信息。
org.apache.shiro.realm.jdbc.JdbcRealm:从数据库获取用户权限等信息。
以后开发一般继承 AuthorizingRealm(授权)抽象类即可;其继承了 AuthenticatingRealm(即身份验证),而且也间接继承了 CachingRealm(带有缓存实现)。

一、单 Realm 配置

1、自定义 Realm 实现(com.luther.shiro.realm.MyRealm1):

public class MyRealm1 implements Realm {

	@Override
	public String getName() {
		return this.getClass().getName();
	}

	@Override
	public boolean supports(AuthenticationToken token) {
		// 只支持UsernamePasswordToken
		return token instanceof UsernamePasswordToken;
	}

	@Override
	public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
		
		// 得到用户名
		String username = usernamePasswordToken.getUsername();
		// 得到密码
		String password = new String(usernamePasswordToken.getPassword());
		
		// 户名错误
		if (!"zhangsan".equals(username)) {
			throw new UnknownAccountException(); 
		}

		// 密码错误
		if (!"123".equals(password)) {
			throw new IncorrectCredentialsException(); 
		}

		System.out.println("用户" + username + "验证成功");

		// 返回
		return new SimpleAccount(username, password, getName());
	}
}

2、ini 配置文件指定自定义 Realm 实现 (shiro-realm.ini)

[main]
#声明一个realm
myRealm1=com.luther.shiro.realm.MyRealm1
#指定securityManager的realms实现,通过 $name 来引入之前的 realm 定义
securityManager.realms=$myRealm1

3、测试用例请参考 com.luther.shiro.authenticator.AuthenticateTest 的testSingleRealm 测试方法,此方法和 testHelloWorld 除了配置文件其它没有差异。

二、多 Realm 配置

1、ini 配置文件(shiro-multi-realm.ini)

[main]
#声明一个realm
myRealm1=com.luther.shiro.realm.MyRealm1
#声明一个realm
myRealm2=com.luther.shiro.realm.MyRealm2
#指定securityManager的realms实现,通过 $name 来引入之前的 realm 定义
securityManager.realms=$myRealm2,$myRealm1

#此例子中显视的指定了顺序为myRealm2,myRealm1。(可以少指定,比如只指定myRealm2,则myRealm1会被忽略)
#如果不指定securityManager.realms,则会按realm的声明(无需设置 realms 属性,其会自动发现)顺序来,此处即为myRealm1,myRealm2。

2、测试用例请参考 com.luther.shiro.authenticator.AuthenticateTest 的 testMutiRealm 测试方法。

Authenticator 及 AuthenticationStrategy

一、Authenticator 及 AuthenticationStrategy简介
Authenticator 的职责是验证用户帐号,是 Shiro API 中身份验证核心的入口点(默认实现为 ModularRealmAuthenticator ),其方法定义为:

public AuthenticationInfo authenticate(AuthenticationToken authenticationToken) throws AuthenticationException;

如果验证成功,将返回 AuthenticationInfo 验证信息;此信息中包含了身份及凭证;如果验证失败将抛出相应的 AuthenticationException 实现。

AuthenticationStrategy 则是 Authenticator 进行验证时的验证策略 (默认实现为:AtLeastOneSuccessfulStrategy),Shiro API 自带的策略有以下三种:
FirstSuccessfulStrategy:只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证成功的认证信息,其他的忽略。
AtLeastOneSuccessfulStrategy:只要有一个 Realm 验证成功即可,和 FirstSuccessfulStrategy 不同,返回所有 Realm 身份验证成功的认证信息。
AllSuccessfulStrategy:所有 Realm 验证成功才算成功,且返回所有 Realm 身份验证成功的认证信息,如果有一个失败就失败了。

二、Authenticator 及 AuthenticationStrategy演示
假设我们有三个 realm:
myRealm1: 用户名/密码为 zhangsan/123 时成功,且返回身份/凭据为 zhangsan/123;
myRealm2: 用户名/密码为 lisi/123 时成功,且返回身份/凭据为 lisi/123;
myRealm3: 用户名/密码为 zhangsan/123 时成功,且返回身份/凭据为 zhangsan.qq/123

1、通用化登录逻辑

private void authentition(String iniConfigPath, String username, String password) {
	// 使用Ini配置文件初始化SecurityManager
	Factory factory = new IniSecurityManagerFactory(iniConfigPath);
	// 得到SecurityManager实例 并绑定给SecurityUtils
	SecurityManager securityManager = factory.getInstance();
	SecurityUtils.setSecurityManager(securityManager);
	
	// 得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
	Subject subject = SecurityUtils.getSubject();
	UsernamePasswordToken token = new UsernamePasswordToken(username, password);
	// 记住用户
	token.setRememberMe(Boolean.TRUE);
	
	try {
		// 登录
		subject.login(token);
		System.out.println("用户zhangsan登录成功,其身份标识为" + subject.getPrincipals());
	} catch (AuthenticationException e) {
		System.err.println("登录失败,失败原因:");
		e.printStackTrace();
	}
	
	assertTrue("用户已验证成功", subject.isAuthenticated());
	
	// 退出
	subject.logout();
}

2、测试 AtLeastOneSuccessfulStrategy
2.1 ini 配置文件 (shiro-firstSuccessfulStrategy.ini)

[main]
#指定securityManager的authenticator实现,可以不指定,因为其默认实现就是ModularRealmAuthenticator
#authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
#securityManager.authenticator=$authenticator

#指定securityManager.authenticator的authenticationStrategy,可以不指定,因为其默认实现就是AtLeastOneSuccessfulStrategy
#authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
#securityManager.authenticator.authenticationStrategy=$authenticationStrategy

#声明一个realm
myRealm1=com.luther.shiro.realm.MyRealm1
#声明一个realm
myRealm2=com.luther.shiro.realm.MyRealm2
#声明一个realm
myRealm3=com.luther.shiro.realm.MyRealm3
#指定securityManager的realms实现,通过 $name 来引入之前的 realm 定义
securityManager.realms=$myRealm3,$myRealm2,$myRealm1

2.2 测试代码

/**
 * 演示AtLeastOneSuccessfulStrategy的效果
 * 每个realm都会进行验证,并返回全部的成功用户标识
 * @author luther
 * @time 2019年7月5日  上午11:30:24
 */
@Test
public void testAtLeastOneSuccessfulStrategy() {
	authentition("classpath:shiro-atLeastOneSuccessfulStrategy.ini", "zhangsan", "123");
}

2.3 测试结果

开始验证com.luther.shiro.realm.MyRealm3
com.luther.shiro.realm.MyRealm3 - 用户zhangsan验证成功
开始验证com.luther.shiro.realm.MyRealm2
开始验证com.luther.shiro.realm.MyRealm1
com.luther.shiro.realm.MyRealm1 - 用户zhangsan验证成功
用户zhangsan登录成功,其身份标识为zhangsan.qq,zhangsan

即 PrincipalCollection 包含了 zhangsan 和 zhangsan.qq 身份信息。

3、测试 AllSuccessfulStrategy
3.1 ini 配置文件 (shiro-allSuccessfulStrategy.ini)

[main]
#指定securityManager的authenticator实现,可以不指定,因为其默认实现就是ModularRealmAuthenticator
#authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
#securityManager.authenticator=$authenticator

#指定securityManager.authenticator的authenticationStrategy为AllSuccessfulStrategy
authenticationStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$authenticationStrategy

#声明一个realm
myRealm1=com.luther.shiro.realm.MyRealm1
#声明一个realm
myRealm2=com.luther.shiro.realm.MyRealm2
#声明一个realm
myRealm3=com.luther.shiro.realm.MyRealm3
#指定securityManager的realms实现,通过 $name 来引入之前的 realm 定义
securityManager.realms=$myRealm3,$myRealm2,$myRealm1

3.2 测试代码

/**
 * 演示AllSuccessfulStrategy的效果
 * 依次对每个realm进行验证,验证通过下一个,验证失败,直接返回失败验证原因,只有全部成功时才返回全部的用户标识
 * 每个realm都会进行验证,并返回全部的成功用户标识
 * @author luther
 * @time 2019年7月5日  上午11:30:24
 */
@Test
public void testAllSuccessfulStrategy() {
	authentition("classpath:shiro-allSuccessfulStrategy.ini", "zhangsan", "123");
}

3.3 测试结果

开始验证com.luther.shiro.realm.MyRealm3
com.luther.shiro.realm.MyRealm3 - 用户zhangsan验证成功
开始验证com.luther.shiro.realm.MyRealm2
登录失败,失败原因:
org.apache.shiro.authc.UnknownAccountException
	at com.luther.shiro.realm.MyRealm2.getAuthenticationInfo(MyRealm2.java:42)
	······

4、测试 firstSuccessfulStrategy
4.1 ini 配置文件 (shiro-firstSuccessfulStrategy.ini)

[main]
#指定securityManager的authenticator实现,可以不指定,因为其默认实现就是ModularRealmAuthenticator
#authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
#securityManager.authenticator=$authenticator

#指定securityManager.authenticator的authenticationStrategy为FirstSuccessfulStrategy
authenticationStrategy=org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$authenticationStrategy

#声明一个realm
myRealm1=com.luther.shiro.realm.MyRealm1
#声明一个realm
myRealm2=com.luther.shiro.realm.MyRealm2
#声明一个realm
myRealm3=com.luther.shiro.realm.MyRealm3
#指定securityManager的realms实现,通过 $name 来引入之前的 realm 定义
securityManager.realms=$myRealm3,$myRealm2,$myRealm1

4.2 测试代码

/**
 * 演示FirstSuccessfulStrategy的效果
 * 会对每个realm进行验证,全部验证完后会返回验证成功的第一个用户标识(此处需注意,不是依次验证立马返回,而是全部验证再返回)
 * @author luther
 * @time 2019年7月5日  上午11:30:24
 */
@Test
public void testFirstSuccessfulStrategy() {
	authentition("classpath:shiro-firstSuccessfulStrategy.ini", "zhangsan", "123");
}

4.3 测试结果

开始验证com.luther.shiro.realm.MyRealm3
com.luther.shiro.realm.MyRealm3 - 用户zhangsan验证成功
开始验证com.luther.shiro.realm.MyRealm2
开始验证com.luther.shiro.realm.MyRealm1
com.luther.shiro.realm.MyRealm1 - 用户zhangsan验证成功
用户zhangsan登录成功,其身份标识为zhangsan.qq

以上已经演示了API自带的验证策略,以下稍微演示下自定义的验证策略。
自定义 AuthenticationStrategy 实现之前,首先简单看其 API:

//在所有Realm验证之前调用
AuthenticationInfo beforeAllAttempts(
Collection realms, AuthenticationToken token) 
throws AuthenticationException;
//在每个Realm之前调用
AuthenticationInfo beforeAttempt(
Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) 
throws AuthenticationException;
//在每个Realm之后调用
AuthenticationInfo afterAttempt(
Realm realm, AuthenticationToken token, 
AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t)
throws AuthenticationException;
//在所有Realm之后调用
AuthenticationInfo afterAllAttempts(
AuthenticationToken token, AuthenticationInfo aggregate) 
throws AuthenticationException;

5、自定义验证策略(com.luther.shiro.authenticationStrategy.LastSuccessfulStrategy)

/**
 * 验证所有realm,并返回最后一个验证通过的身份标识
 * @author luther
 * @time 2019年7月5日  下午4:12:31
 */
public class LastSuccessfulStrategy extends AbstractAuthenticationStrategy {
	
	// 第一种方案修改afterAttempt方法
	@Override
	public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo,
			AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
		return singleRealmInfo;
	}

//	// 第二种方案修改merge方法
//	@Override
//	protected AuthenticationInfo merge(AuthenticationInfo info, AuthenticationInfo aggregate) {
//		if (info != null) {
//			aggregate = info;
//		}
//		
//		return aggregate;
//	}
	
}

5.1 ini 配置文件 (shiro-lastSuccessfulStrategy.ini)

[main]
#指定securityManager的authenticator实现,可以不指定,因为其默认实现就是ModularRealmAuthenticator
#authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
#securityManager.authenticator=$authenticator

#指定securityManager.authenticator的authenticationStrategy为自定义的LastSuccessfulStrategy
authenticationStrategy=com.luther.shiro.authenticationStrategy.LastSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$authenticationStrategy

#声明一个realm
myRealm1=com.luther.shiro.realm.MyRealm1
#声明一个realm
myRealm2=com.luther.shiro.realm.MyRealm2
#声明一个realm
myRealm3=com.luther.shiro.realm.MyRealm3
#指定securityManager的realms实现,通过 $name 来引入之前的 realm 定义
securityManager.realms=$myRealm3,$myRealm2,$myRealm1

5.2 测试代码

/**
 * 演示自定义的LastSuccessfulStrategy的效果
 * 会对每个realm进行验证,全部验证完后会返回验证成功的最后一个用户标识	
 * @author luther
 * @time 2019年7月5日  上午11:30:24
 */
@Test
public void testLastSuccessfulStrategy() {
	authentition("classpath:shiro-lastSuccessfulStrategy.ini", "zhangsan", "123");
}

5.3 测试结果

开始验证com.luther.shiro.realm.MyRealm3
com.luther.shiro.realm.MyRealm3 - 用户zhangsan验证成功
开始验证com.luther.shiro.realm.MyRealm2
开始验证com.luther.shiro.realm.MyRealm1
com.luther.shiro.realm.MyRealm1 - 用户zhangsan验证成功
用户zhangsan登录成功,其身份标识为zhangsan

上述就是小编为大家分享的什么是Shiro验证了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。


网站标题:什么是Shiro验证
浏览路径:http://www.tsicrk.com/article/gcjdci.html

其他资讯

让你的专属顾问为你服务

0.6807s