Shiro的安装和基本使用

shiro中的核心架构

添加依赖到 pom.xml

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.7.0</version></dependency>

shiro配置文件 .ini 结尾文件(类似.txt)

ini 配置文件 用来学习shiro书写我们系统中相关权限数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VI45CZZE-1614147077413)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210223093230598.png)]

测试shiro

package com.zxh.shiro;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;/*** @author: AmberZxh* @DateTime: 2021/2/23 9:35 上午* @description:*/
public class TestAuthenticator {public static void main(String[] args) {// 1 . 创建安全管理器对象DefaultSecurityManager securityManager = new DefaultSecurityManager();// 2. 给安全管理器设置realmsecurityManager.setRealm(new IniRealm("classpath:shiro.ini"));// 3. 全局安全工具类 SecurityUtils// 设置安全管理器SecurityUtils.setSecurityManager(securityManager);// 4. 关键对象 subject主体Subject subject = SecurityUtils.getSubject();// 5. 创建令牌UsernamePasswordToken token = new UsernamePasswordToken("xiaozhang","zhang");try{System.out.println("认证状态" + subject.isAuthenticated());subject.login(token);  // 用户认证System.out.println("认证状态" + subject.isAuthenticated());}catch (UnknownAccountException e){e.printStackTrace();System.out.println("认证失败:用户名不存在");}catch (IncorrectCredentialsException e){e.printStackTrace();System.out.println("认证失败:密码不存在");}}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CboTD1nZ-1614147077415)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210223095607234.png)]

步骤:

  • 创建安全管理器对象 DefaultSecurityManager

  • 给安全管理器设置realm(以后到数据库中取)

什么是realm ?

​ 对于什么是Realm,我使用过之后,个人总结一下:shiro要进行身份验证,就要从realm中获取相应的身份信息来进行验证,简单来说,我们可以自行定义realm,在realm中,从数据库获取身份信息,然后和 用户输入的身份信息进行匹配。这一切都由我们自己来定义。

  • 设置全局安全工具类 SecurityUtils

  • 得到关键对象

  • 创建令牌

  • 验证

运行结果:账号密码正确

运行结果:账号不正确

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MnibvueI-1614147077416)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210223095853308.png)]

运行结果:密码不正确

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CYqHFKoP-1614147077417)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210223095931005.png)]

UnknownAccountException 用户名不存在异常

IncorrectCredentialsException 密码错误异常

Shiro 源码解析

认证:

  1. 最终执行用户名比较在 SimpleAccountRealm 类中

    doGetAuthenticationInfo 在这个方法中完成了用户名的校验

  2. 最终密码校验是在 AuthenticatingRealm 中

​ assertCredentialsMatch (Credential 凭证)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DojMZqpl-1614147077418)(/Users/zhangxuhui/Desktop/笔记/Xnip2021-02-23_14-13-01.jpg)]

总结

AuthenticatingRealm 认证realm doGetAuthenticationInfo(以后我们要覆盖)

AuthorizingRealm 授权realm doGetAuthorizationInfo(以后我们要覆盖)

SimpleAccountRealm 继承 AuthenticatingRealmAuthorizingRealm

所以,它有了认证和授权的权利。

自定义realm进行验证

创建这两个对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ySMq0kSY-1614147077418)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210223151011967.png)]

CustomerRealm.java

package com.zxh.shiro.realm;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;/*** @author: AmberZxh* @DateTime: 2021/2/23 2:29 下午* @description:** 自定义realm实现,将认证/授权数据的数据库的来源转为数据库的实现*/
public class CustomerRealm extends AuthorizingRealm {/***  授权* @param principals* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}/***  认证* @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// 在token中获取用户名String principal = (String)token.getPrincipal();System.out.println(principal);// 根据身份信息使用jdbc mybatis查询相关数据库if("xiaozhang".equals(principal)){// 参数1 返回数据库中正确用户名// 参数2 返回数据库中正确密码// 参数3 提供当前realm的名字, this.getName()SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo("xiaozhang","123",this.getName());return simpleAuthenticationInfo;}return null;}
}

TestCustormerRealmAuthenticator.java

package com.zxh.shiro.test;import com.zxh.shiro.realm.CustomerRealm;
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.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;/*** @author: AmberZxh* @DateTime: 2021/2/23 2:33 下午* @description:* 使用自定义realm*/
public class TestCustomerRealmAuthenticator {public static void main(String[] args) {// 创建securityManagerDefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();// 设置自定义realmdefaultSecurityManager.setRealm(new CustomerRealm());// 设置安全工具类SecurityUtils.setSecurityManager(defaultSecurityManager);// 通过安全工具类 获取subjectSubject subject = SecurityUtils.getSubject();// 创建tokenUsernamePasswordToken token = new UsernamePasswordToken("xiaozhang", "123");try {subject.login(token);System.out.println(subject.isAuthenticated());} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误");}catch (IncorrectCredentialsException e){e.printStackTrace();System.out.println("密码错误");}}
}

以上就是一些基本原理和使用了


MD5+salt

MD5:

  1. 作用:一般用来加密或者签名
  2. 特点:MD5算法不可逆,内容相同无论执行多少次MD5生成结果始终是一致

流程

我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如MD5密码破解网站),得到某用户的密码。

加Salt可以一定程度上解决这一问题。所谓加Salt方法,就是加点“佐料”。其基本想法是这样的:当用户首次提供密码时(通常是注册时),由系统自动往这个密码里撒一些“佐料”,然后再散列。而当用户登录时,系统为用户提供的代码撒上同样的“佐料”,然后散列,再比较散列值,已确定密码是否正确。

这里的“佐料”被称作“Salt值”,这个值是由系统随机生成的,并且只有系统知道。这样,即便两个用户使用了同一个密码,由于系统为它们生成的salt值不同,他们的散列值也是不同的。即便黑客可以通过自己的密码和自己生成的散列值来找具有特定密码的用户,但这个几率太小了(密码和salt值都得和黑客使用的一样才行)。

下面详细介绍一下加Salt散列的过程。介绍之前先强调一点,前面说过,验证密码时要使用和最初散列密码时使用“相同的”佐料。所以Salt值是要存放在数据库里的。

用户注册时,

  1. 用户输入【账号】和【密码】(以及其他用户信息);
  2. 系统为用户生成【Salt值】;
  3. 系统将【Salt值】和【用户密码】连接到一起;
  4. 对连接后的值进行散列,得到【Hash值】;
  5. 将【Hash值1】和【Salt值】分别放到数据库中。

用户登录时,

  1. 用户输入【账号】和【密码】;
  2. 系统通过用户名找到与之对应的【Hash值】和【Salt值】;
  3. 系统将【Salt值】和【用户输入的密码】连接到一起;
  4. 对连接后的值进行散列,得到【Hash值2】(注意是即时运算出来的值);
  5. 比较【Hash值1】和【Hash值2】是否相等,相等则表示密码正确,否则表示密码错误。

有时候,为了减轻开发压力,程序员会统一使用一个salt值(储存在某个地方),而不是每个用户都生成私有的salt值。

Shiro中使用MD5并加盐

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-celiUTF0-1614147077419)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210224110021194.png)]

package com.zxh.shiro.test;import org.apache.shiro.crypto.hash.Md5Hash;/*** @author: AmberZxh* @DateTime: 2021/2/24 9:01 上午* @description:*/
public class TestShiroMD5 {public static void main(String[] args) {// 使用md5Md5Hash md5Hash = new Md5Hash("123");System.out.println(md5Hash);// 使用md5 + salt处理Md5Hash md5Hash1 = new Md5Hash("123", "X0*7ps");System.out.println(md5Hash1);// 使用md5 + salt + hash散列Md5Hash md5Hash2 = new Md5Hash("123", "X0*7ps", 1024);System.out.println(md5Hash2);}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f6Spp2nY-1614147077419)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210224110049799.png)]

重写密码匹配器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O7uWyO3M-1614147077419)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210224135117955.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-icQsxIla-1614147077419)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210224140057768.png)]

package com.zxh.shiro.test;import com.zxh.shiro.realm.CustomerMd5Realm;
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.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;/*** @author: AmberZxh* @DateTime: 2021/2/24 9:17 上午* @description:*/
public class TestCustomerMd5RealmAuthenticator {public static void main(String[] args) {// 创建安全管理器DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();// 注入realmCustomerMd5Realm realm = new CustomerMd5Realm();// 创建密码匹配器HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();// 告诉密码匹配器使用的是 md5credentialsMatcher.setHashAlgorithmName("md5");realm.setCredentialsMatcher(credentialsMatcher);defaultSecurityManager.setRealm(realm);// 将安全管理器注入安全工具类SecurityUtils.setSecurityManager(defaultSecurityManager);// 通过安全工具类获取 subjectSubject subject = SecurityUtils.getSubject();// 认证UsernamePasswordToken token = new UsernamePasswordToken("xiaozhang", "123");try {subject.login(token);System.out.println("登录成功");} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误");} catch (IncorrectCredentialsException e){e.printStackTrace();System.out.println("密码错误");}}
}

告诉shiro我们的md5和随机盐

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qLoGSICD-1614147077420)(/Users/zhangxuhui/Library/Application Support/typora-user-images/image-20210224140210540.png)]

package com.zxh.shiro.realm;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;
import org.apache.shiro.util.ByteSource;/*** @author: AmberZxh* @DateTime: 2021/2/24 9:14 上午* @description: 使用自定义realm 加入md5+salt+ hash散列*/
public class CustomerMd5Realm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// 获取身份信息String principal = (String) token.getPrincipal();// 根据用户名查询数据库if ("xiaozhang".equals(principal)) {// 参数一 :数据库用户名// 参数二 :数据库md5 + salt之后的密码// 参数三 : 注册时的随机盐// 参数四 : realm的名字return new SimpleAuthenticationInfo(principal, "e4f9bf3e0c58f045e62c23c533fcf633",ByteSource.Util.bytes("X0*7ps"),this.getName());}return null;}
}

完整的test(完成了散列次数的设置)

CustomerMd5Realm.java

package com.zxh.shiro.realm;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;
import org.apache.shiro.util.ByteSource;/*** @author: AmberZxh* @DateTime: 2021/2/24 9:14 上午* @description: 使用自定义realm 加入md5+salt+ hash散列*/
public class CustomerMd5Realm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// 获取身份信息String principal = (String) token.getPrincipal();// 根据用户名查询数据库if ("xiaozhang".equals(principal)) {// 参数一 :数据库用户名// 参数二 :数据库md5 + salt之后的密码// 参数三 : 注册时的随机盐// 参数四 : realm的名字return new SimpleAuthenticationInfo(principal, "e4f9bf3e0c58f045e62c23c533fcf633",ByteSource.Util.bytes("X0*7ps"),this.getName());}return null;}
}

TestCustomerMd5RealmAuthenicator.java

package com.zxh.shiro.test;import com.zxh.shiro.realm.CustomerMd5Realm;
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.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;/*** @author: AmberZxh* @DateTime: 2021/2/24 9:17 上午* @description:*/
public class TestCustomerMd5RealmAuthenticator {public static void main(String[] args) {// 创建安全管理器DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();// 注入realmCustomerMd5Realm realm = new CustomerMd5Realm();// 创建密码匹配器HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();// 告诉密码匹配器使用的是 md5credentialsMatcher.setHashAlgorithmName("md5");// 告诉密码匹配器的散列次数credentialsMatcher.setHashIterations(1024);realm.setCredentialsMatcher(credentialsMatcher);defaultSecurityManager.setRealm(realm);// 将安全管理器注入安全工具类SecurityUtils.setSecurityManager(defaultSecurityManager);// 通过安全工具类获取 subjectSubject subject = SecurityUtils.getSubject();// 认证UsernamePasswordToken token = new UsernamePasswordToken("xiaozhang", "123");try {subject.login(token);System.out.println("登录成功");} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误");} catch (IncorrectCredentialsException e){e.printStackTrace();System.out.println("密码错误");}}
}

密码 ‘’123‘’ 的各种散列

md5                      = 202cb962ac59075b964b07152d234b70
md5 + salt               = 8a83592a02263bfe6752b2b5b03a4799
md5 + salt + hash散列次数 = e4f9bf3e0c58f045e62c23c533fcf633

Shiro的安装和基本使用相关推荐

  1. 在 Web 项目中应用 Apache Shiro

    Apache Shiro 是功能强大并且容易集成的开源权限框架,它能够完成认证.授权.加密.会话管理等功能.认证和授权为权限控制的核心,简单来说,"认证"就是证明你是谁? Web ...

  2. Shiro第一个程序:官方快速入门程序Qucickstart详解教程

    目录 一.下载解压 二.第一个Shiro程序 1. 导入依赖 2. 配置shiro配置文件 3. Quickstart.java 4. 启动测试 三.shiro.ini分析 四.Quickstart. ...

  3. Spring Boot+JWT+Shiro+MyBatisPlus实现Restful快速开发后端脚手架

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:我叫刘半仙 链接:my.oschina.net/liughD ...

  4. SpringBoot+JWT+Shiro+MybatisPlus实现Restful快速开发后端脚手架

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:lywJee cnblogs.com/lywJ/p/1125 ...

  5. 分布式架构spring mvc +mybatis +shiro+ Activiti +Alibaba Druid

    介绍 jeesz-utils jeesz-config jeesz-framework jeesz-core-cms jeesz-core-gen jeesz-core-bookmark jeesz- ...

  6. Shiro 教程,Shiro教程0.2 下载,Shiro功能修复与升级说明。

    2019独角兽企业重金招聘Python工程师标准>>> Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载? 原文链接:http ...

  7. Shiro 权限框架使用总结

    我们首先了解下什么是shiro ,Shiro 是 JAVA 世界中新近出现的权限框架,较之 JAAS 和 Spring Security,Shiro 在保持强大功能的同时,还在简单性和灵活性方面拥有巨 ...

  8. 将 Shiro 作为应用的权限基础

    Shiro 是 Java 世界中新近出现的权限框架,较之 JAAS 和 Spring Security,Shiro 在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势.本文介绍了 Shiro 的 ...

  9. 【Redis】Redis介绍与Redis3在Window下的安装

    转载请注明出处http://blog.csdn.net/qq_26525215 本文源自[大学之旅_谙忆的博客] 前言 其实在今天之前我都不知道Redis是什么东西.至于为什么知道了这个东西而且又要去 ...

最新文章

  1. anaconda spyder使用协程报错解决:RuntimeError: This event loop is already running
  2. Linux命令——find详解
  3. 字典数(前缀树)的实现
  4. 网络编程中BIO和NIO的区别
  5. centos安装python3.4 pip3
  6. [Regionals 2012 :: Asia - Tokyo ]
  7. python修复不了_python-如何修复cm.spectral(模块“ matplotlib.cm”...
  8. 4_1 古老的密码(UVa1339)排序
  9. tfs nginx 端口调用失败?
  10. php调用第三方接口代码,PHP接口编程——调用第三方接口获取天气
  11. mysql查询时间段内数据
  12. JavaScript实现图片上传并预览并提交
  13. 英语时态=时间+状态
  14. linux txt转化vcf命令,【9.2更新】Vcf转换工具(Excel、TXT转Vcf 和 Vcf转Excel)
  15. C# 读取 vCard 格式
  16. html 引入gif 不会动,GIF图片在电脑上不会动的解决办法
  17. 3344avd_AVD生根
  18. Excel 2019:二级级联下拉框设置
  19. 《C系列-实践相关》C语言十
  20. 服装ERP软件体系究竟差在哪里?

热门文章

  1. freeCAD part工作台,两个物体做合集相加的布尔组合先后顺序区别
  2. 部署Tomcat服务器
  3. 造命者天,立命者我_huadingjin_新浪博客
  4. 电脑没有WiFi断网代码56解决方法CCleaner下载
  5. 树莓派有线网络设置_树莓派设置固定IP之有线网和无线网方法
  6. 啊哈 , 算法 !--深度优先搜索( C语言版 )
  7. 让虚拟机接入办公网络
  8. Java24种设计模式(第二种)--代理模式(Proxy Pattern)
  9. 传统产业如何进行数字化转型
  10. 【CSS】自定义平台文章封面图