shiro 字段不是username 和password_Shiro--->01

什么是Shiro

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

架构图-Shiro外部

Subject,理解为当前用户的安全操作
ShiroSecurityManager,Shiro框架的核心。安全管理器,所有与安全有关系的操作,都会与ShiroSecurityManager进行交互,并且管理着所有的Subject。
Realm,充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。

b176ff94e962b03f41b2c0fa981621ae.png

架构图-Shiro内部

Authenticator,负责主体认证。
Authorizer,用来决定主体是否有权限进行操作
Realms,可以有1个或多个,安全实体的数据源。
SessionManager,用来管理主体与应用之间交互的数据。
SessionDao,用于会话的增删改查。
CacheManager,用来管理用户、角色、权限的缓存
Cryptography,密码模块,shiro提供了一套加密/解密的组件。

ce4de2fe6cec79f0d6fac1ce32178a0c.png

Shiro常用名词

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

Shiro配置文件

ini文件中主要配置有四大类:main,users,roles,urls
main,主要配置shiro的一些对象,例如securityManager ,Realm, authenticator,authcStrategy 等等。
users,允许配置一组静态的用户,包含用户名,密码,角色,一个用户 可以有多个角色,可以配置多个角色。
roles,将角色和权限关联起来。
urls, 配置主要在web应用中,格式为:url=拦截器[参数],拦截器[参 数]……

shiro.ini文件放在classpath下,shiro会自动查找,其中格式是key/value 键值对配置。 

f2bc7bd461247c2fdccade88f5170224.png

Realm

Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息。
[main]
#配置Realm
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
#配置数据源
dataSource = com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass = com.mysql.jdbc.Driver
dataSource.jdbcUrl = jdbc:mysql://localhost:3306/test? serverTimezone=GMT&characterEncoding=UTF-8
dataSource.user = root
dataSource.password =123456

jdbcRealm.dataSource = $dataSource

#将Realm注入给SecurityManager
securityManager.realm = $jdbcRealm

如果使用的是JdbcRealm,那么数据表名和字段名都必须写成users、username、password,因为JdbcRealm的底层源码中就已经对表名和字段名做出了规定。

77a1860fb8449529fa9ddaf5078620f1.png

自定义Realm,登录认证

自定义Realm,可以注入给securityManager更加灵活的安全数据源。也就是说我们可以随意起数据表名以及字段名称了。
1、导入jar包。
        shiro-all-1.3.2.jar
	junit-4.9.jar
	log4j-1.2.17.jar
	shiro-all-1.3.2.jar
	slf4j-api-1.7.5.jar
	slf4j-log4j12-1.7.5.jar
        com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
        commons-beanutils-1.9.2.jar
        commons-logging-1.1.1.jar
2、创建Shiro.ini配置文件。

a66784e70d0344193d76a48a965d61a3.png
3、创建类继承抽象方法AuthenticatingRealm,需要重写方法。该方法可以理解为是认证方法。也可以去继承AuthorizingRealm,该类下面有两个方法
需要重写,一个是认证方法,一个是授权方法。当通过认证方法后,可以对该访问进行授权。

45df1248d8266c9cf7400d6215ad4581.png
继承AuthenticatingRealm,重写方法
4、因为是自定义Realm,需要自己编写代码去操作数据库,这一步就创建数据库连接对象操作数据库进行查询。
5、将查询结果存储到临时变量中,并将结果返回。
6、编写测试类测试。

29e2112ad4465af4db8c2e88d986aa79.png
测试类

认证执行流程

获取ini配置文件,创建securityManager
subject执行login(token)提交认证,最终由securityManager调用Authenticator 
Authenticator调用realm查询用户信息 
realm根据token(usernamePasswordToken)中的账号查询用户信息,如果找不到则给Authenticator返回null,如果找到realm则再去匹配密码,匹配密码成功则认证通过。

MD5加密、加盐与迭代 01

fba57b869d1bcd7c5bb9de0d755485ce.png
Md5Hash的几个重载方法,source,代表数据源。salt,加盐。hashIterations,代表迭代次数。
public class MD5Test {
	@Test
	public void testMD5(){
		//MD5加密,创建一个由Shiro提供的Md5Hash类。
		Md5Hash md5Hash = new Md5Hash("123");
		System.out.println(md5Hash);
		//MD5加盐
		Md5Hash md5Hash2 = new Md5Hash("123", "随机字符串");
		System.out.println(md5Hash2);
		//迭代
		Md5Hash md5Hash3 = new Md5Hash("123", "随机字符串", 2);
		System.out.println(md5Hash3);
	}
}

//输出结果
202cb962ac59075b964b07152d234b70
4e7fbf83ecb3d4f22c47722dc964a422
da420611b5a4dd7510816745803b9c98

MD5凭证匹配器实现

/**
*将迭代加密后的结果存储到数据库中,再查询。
*/
public class CustomRealm extends AuthenticatingRealm{
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//提取变量
		String principal =null;
		String credentials=null;
		String salt = null;
		ResultSet rs = null;
		Statement stm = null;
		Connection conn = null;
		//加载驱动
		try {
			DriverManager.registerDriver(new Driver());
			//获取连接对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test? serverTimezone=GMT&characterEncoding=UTF-8", "root", "123456");
			//创建操作对象
			stm = conn.createStatement();
			//执行sql语句
			String sql = "select userName,passwd,passwd_salt from starLogin";
			rs = stm.executeQuery(sql);
			//循环遍历
			while(rs.next()){
				principal = rs.getString("userName");
				credentials = rs.getString("passwd");
				salt = rs.getString("passwd_salt");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(rs != null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(stm != null){
				try {
					stm.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		
		/**
		 * 重写的为接口,需要创建它的实现类。SimpleAuthenticationInfo构造器重载方法中需要有一个ByteSource类型的加密盐,
		     需要对其进行数据库中获取到的字符串的盐进行转换。
		 */
		ByteSource newSalt = ByteSource.Util.bytes(salt);
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, credentials, newSalt,"customRealm");
		return simpleAuthenticationInfo;	
	}
}
Shiro配置文件
[main]
#配置凭证匹配器
credentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher

#设置凭证匹配器的相关属性
credentialsMatcher.hashAlgorithmName = MD5
#迭代次数
credentialsMatcher.hashIterations = 2

#配置Realm
customRealm = com.sxt.realms.CustomRealm

#配置Realm的凭证属性器
customRealm.credentialsMatcher = $credentialsMatcher

#将Reaml注入给SucurityManager
securityManager.realm = $customRealm

授权

425cfc84efc98bb742e5f323d6ec9196.png
授权。访问控制,是对资源的访问管理的过程。当认证成功之后,开始权限控制。
	/**
	 * 授权,访问控制,是对资源的访问管理的过程。即对于 认证通过的用户,授予他可以访问某些资源的权限。
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		//提取变量
		String roleName= null;
		String remark = null;
		ResultSet rs = null;
		Statement stm = null;
		Connection conn = null;
		
		//加载驱动
		try {
			DriverManager.registerDriver(new Driver());
			//获取连接对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/shiro? serverTimezone=GMT&characterEncoding=UTF-8", "root", "123456");
			//创建操作对象
			stm = conn.createStatement();
			//执行sql语句
//			String sql = "select name from role";
			String sql = "select remark from permission";
			rs = stm.executeQuery(sql);
			//循环遍历
			if(rs.first()){
//				roleName = rs.getString("name");
				remark = rs.getString("remark");
				
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(rs != null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(stm != null){
				try {
					stm.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//		info.addRole(roleName);
		info.addStringPermission(remark);//把权限添加进去
		return info;
	}


/**
 * 测试类
 *
 */
public class AuthorizationTest {
	@Test
	public void testAuthorization(){
		//1、构建SecurityManager工厂
		IniSecurityManagerFactory SecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
		//2、通过SecurityManagerFactory获取SecurityManager实例
		SecurityManager securityManager = SecurityManagerFactory.getInstance();
		//3、将securityManager设置到运行环境中
		SecurityUtils.setSecurityManager(securityManager);
		//4、获取Subject实例
		Subject subject = SecurityUtils.getSubject();
		//5、创建用户名密码验证令牌
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");
		//6、进行身份验证
		subject.login(token);
		//7、判断是否认证通过
		System.out.println("认证是否通过:"+subject.isAuthenticated());
		//授权操作
		//基于角色授权
		System.out.println("角色授权:"+subject.hasRole("管理员"));
		//资源授权
		System.out.println("权限授权:"+subject.isPermitted("一级菜单,基本设置操作权限"));
		
	}
}

Shiro.ini配置文件
[main]
#配置Realm
customRealm = com.sxt.realms.CustomRealm

#将Realm注入给SecurityManager
securityManager.realm = $customRealm
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值