Live2d Test Env

shiro安全框架

shiro是Apache提供的安全框架,主要有四大功能:认证(即登录认证)、授权(授权用户拥有访问哪些资源权限)、回话管理(管理用户的session)以及加密(数据加密)。

首先创建一个javase或者javaee项目,我是建立的javaee项目,首先创建一个简单的shiro项目。

一、shiro认证

在src下创建一个名为shiro.ini的文件,文件内容写入:

[users]
zhangsan=123456

[users]表示是用户组,zhangsan是用户名,123456是密码,只是简单的连接,就不需要直接从数据库获取了,随后会讲从如何使用shiro连接数据库实现认证。

导入架包:

写一个测试代码实现基本的认证:

package com.yjb.text;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.util.Factory;

import com.yjb.shiroutis.ShiroSubject;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;

public class Text {
public static void main(String[] args) {
	//获取SecurityManager工厂对象
	Factory<SecurityManager> foctory=new IniSecurityManagerFactory("classpath:shiro.ini");
	//获取SecurityManager实例对象
	SecurityManager securityManager=foctory.getInstance();
	//将SecurityManager实例兑现设置到运行环境中
	SecurityUtils.setSecurityManager(securityManager);
	//获取subject实体
	Subject subject=SecurityUtils.getSubject();
	//获取token,用于与shiro文件数据进行比对
	UsernamePasswordToken token=new UsernamePasswordToken("zhangsan", "123456");
	//shiro登录,
	subject.login(token);
	
	if(subject.isAuthenticated()){//isAuthenticated()的返回值为true表示比对成功
		System.out.println("登录成功");
	}else{
		System.out.println("失败");
	}
}
}

注意事项:

第一点:

在获取SecurityManager工厂对象会报错,这里会报错

new IniSecurityManagerFactory("classpath:shiro.ini");

原因是Apache有一个SecurityManager对象,而java.lang也有一个,所以需要手动导包为import org.apache.shiro.mgt.SecurityManager;或者直接点击错误使用静态导入。

第二点:报错问题

将shiro的配置文件配置为如下:

[users]
张三=123456

然后在获取token处改为
  

 UsernamePasswordToken token=new UsernamePasswordToken("张三", "123456");

运行会报错

log4j:WARN No appenders could be found for logger (org.apache.shiro.io.ResourceUtils).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.apache.shiro.authc.UnknownAccountException: Realm [org.apache.shiro.realm.text.IniRealm@7b6bb7b1] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - 张三, rememberMe=false].
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:184)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
	at com.yjb.text.Text.main(Text.java:26)

原因是配置文件不允许出现中文,往后与ssm框架整合的时候,shiro的配置文件可以改为shiro.xml。现在还不能改。

第三点:出现异常信息

Exception in thread "main" java.lang.IllegalArgumentException: Line argument must contain a key and a value.  Only one string token was found.
	at org.apache.shiro.config.Ini$Section.splitKeyValue(Ini.java:551)
	at org.apache.shiro.config.Ini$Section.toMapProps(Ini.java:576)
	at org.apache.shiro.config.Ini$Section.<init>(Ini.java:473)
	at org.apache.shiro.config.Ini$Section.<init>(Ini.java:454)
	at org.apache.shiro.config.Ini.addSection(Ini.java:311)
	at org.apache.shiro.config.Ini.load(Ini.java:360)
	at org.apache.shiro.config.Ini.load(Ini.java:296)
	at org.apache.shiro.config.Ini.load(Ini.java:284)
	at org.apache.shiro.config.Ini.loadFromPath(Ini.java:253)
	at org.apache.shiro.config.Ini.fromResourcePath(Ini.java:234)

原因是存贮在本地没有存贮为NASI格式,需要统一格式,我的项目格式是utf-8,首先需要在Windows中修改项目空间为utf-8

然后删除shiro.ini文件,重新创建一个,保存到本地是,会变成NASI编码。如果还不行,直接到本地改编码。

第四点:出现错误信息

Exception in thread "main" org.apache.shiro.authc.UnknownAccountException: Realm [org.apache.shiro.realm.text.IniRealm@5ce904c4] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - 12, rememberMe=false].
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:184)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
	at com.yjb.text.Text.main(Text.java:26)

和错误信息:

log4j:WARN No appenders could be found for logger (org.apache.shiro.io.ResourceUtils).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - zhangsan, rememberMe=false] did not match the expected credentials.
	at org.apache.shiro.realm.AuthenticatingRealm.assertCredentialsMatch(AuthenticatingRealm.java:600)
	at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:578)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
	at com.yjb.text.Text.main(Text.java:27)

前者错误为用户名错误,后者为密码错误,需要处理异常:

package com.yjb.text;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.util.Factory;

import com.yjb.shiroutis.ShiroSubject;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;

public class Text {
public static void main(String[] args) {
	//获取SecurityManager工厂对象
	Factory<SecurityManager> foctory=new IniSecurityManagerFactory("classpath:shiro.ini");
	//获取SecurityManager实例对象
	SecurityManager securityManager=foctory.getInstance();
	//将SecurityManager实例兑现设置到运行环境中
	SecurityUtils.setSecurityManager(securityManager);
	//获取subject实体
	Subject subject=SecurityUtils.getSubject();
	//获取token,用于与shiro文件数据进行比对
	UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","12");
	//shiro登录,
	
	try {
		subject.login(token);
		if(subject.isAuthenticated()){//isAuthenticated()的返回值为true表示比对成功
			System.out.println("登录成功");
		}
	} catch (IncorrectCredentialsException e) {
		System.out.println("密码错误");
	}catch (UnknownAccountException e) {
		System.out.println("用户名错误错误");
	}catch (Exception e) {
		System.out.println("用户过期或者被禁用");
	}
}
}

shiro中有很多异常类来处理异常,有用户错误,密码错误,用户过期,密码过期,用户被禁用等异常,主要处理前两个,其他的异常使用Exception 异常处理就够了。

错误类类型

UnknownAccountException:认证异常,即用户名不正确。

DisabledAccountException:账户失效异常。

IncorrectCredentialsException:凭证异常,即密码不正确。

ExpiredCredentialsException:凭证过期。

ExcessiveAttemptsException:尝试次数过多。

2、shiro配置文件讲解

 

shiro的ini文件有四个组,分别:

1,[main]组:用于配置程序的SecurityManager实例以及任何它的依赖组件。

2,[users]组:用于定义一组用户账户,可以包含用户名密码,甚至可以包含角色。

3,[roles]组:用于定义在[users]中的角色与权限关联起来。

[users]组合[roles]组相关关联实例:

[users]
zhangsan=123456,roles1
[roles]
roles1=user:add,user:delete

 

 

3:jdbcRealm

使用c3p0数据库连接池,使用jdbcRealm需要数据库的表名为users,需要有三个字段username,password和password_salt

shiro.ini配置文件

[main]
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysqql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/user
dataSource.user=root
dataSource.password=1232626yjb
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
securityManager.realm=$jdbcRealm
[users]
zhansan=12345

测试代码:

package com.yjb.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;

public class Text {
	public static void main(String[] args) {
		Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini");
		SecurityManager securityManager=factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		Subject subject=SecurityUtils.getSubject();
		UsernamePasswordToken token= new UsernamePasswordToken("lisi","11111");
		try {
			subject.login(token);
			if(subject.isAuthenticated()){
				System.out.println("成功");
			}
		} catch (AuthenticationException e) {
			System.out.println(e);
		}
	}

}

 

4,认证策略

4.1,shiro提供了三种认证策略

AtLeastOneSuccessfulStrategy:只要有一个(或更多)的Realm验证成功,那么认证将被视为成功。

FirstSuccessfulStrategy:只要有一个Realm验证成功,整体认证将被视为成功,且后续Realm将被忽略。

AllSuccessfulStrategy:所有Realm成功,认证才视为成功。

默认认证策略是AtLeastOneSuccessfulStrategy。

4.2,实现认证策略

在securityManager中可以配置验证器,首先需要获取验证策略

在ini文件中配置

authcStrategy =org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy

5,自定义realm

在使用JdbcRealm时,已经规定了数据库中的表名和表字段规范,但是在日常开发中,表名和表字段为realm规定的名字。自定义realm就是为了解决这个问题的。

package com.yjb.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class UserRealm extends AuthorizingRealm {

	@Override
	/*授权*/
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	/*认证*/
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		/*username和password表示从数据库取出的数据
		 在封装到SimpleAuthenticationInfo类中,然后在配置文件中进行配置
		 
		 *
		 */
		String username="zhansan";
		String password="1111";
		SimpleAuthenticationInfo info =new SimpleAuthenticationInfo(username,password,getName());
		return info;
	}

}

 

配置文件:

[main]
user=com.yjb.shiro.UserRealm
securityManager.realm=$user

 

二:加密

shiro提供了一系列加密算法,所在包为:org.apache.shiro.crypto.hash

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-05-20 23:00  waywardcode  阅读(81)  评论(0)    收藏  举报