shiro注册登录流程(如何加密加盐)+配置多个Ream+密码加密验证底层分析+Remember使用+不同密码比对器原理(二)
1.注册
1.1 注册流程
用户输入用户名密码进行注册。
服务端收到用户名密码之后,进行一个加密处理,然后再存到数据库中。
//带盐的加密字符串 Md5Hash zhangsan = new Md5Hash("123", "zhangsan", 1024); System.out.println("zhangsan = " + zhangsan); SimpleHash simpleHash = new SimpleHash("MD5", "123", "lisi", 1024); System.out.println("simpleHash = " + simpleHash);
加密之后,将加密后的密码存入到数据库中。
2.登录
2.1 登录流程
- 登录的时候用户输入用户名密码。
- 登录时候,主要在
com.qfedu.demo.realm.DbRealm#doGetAuthenticationInfo
方法中处理登录逻辑,这个方法主要是根据登录用户名去数据库查询到用户信息,并返回。 - 系统会自动调用
com.qfedu.demo.realm.DbRealm#getCredentialsMatcher
方法中提供的密码比对器,做最后的密码比对操作。
3.登录加密验证
3.1数据库
我们这里设置六个字段
- id 用户id
- username用户名 —>以后都是用用户名进行加盐操作
- password用户密码—> 密码以后要进行加密,有两种加密方法
- MD5
- SHA-512
- nickname暂时用不到
- 权限名(boolean类型)1,0
- 用户权限类型
3.2 密码加密过程
由于我们这里没有写登录功能,我们在测试方法里手动进行密码加密,更便于理解
MainTest
//第一种加密方法,写法不同, 利用 MD5 消息摘要计算 123 的消息摘要Md5Hash md5Hash = new Md5Hash("123");System.out.println("md5Hash = " + md5Hash);
//也可以指定SimpleHash,因为MD5Hash是SimpleHash的子类SimpleHash md5 = new SimpleHash("MD5", "123");System.out.println("md5 = " + md5);//第二种加密方法,写法不同,利用SHA512信息摘要计算123的信息摘要System.out.println("-------------------------------------");System.out.println("new Sha512Hash(\"123\") = " + new Sha512Hash("123"));System.out.println("new SimpleHash(\"SHA-512\",\"123\") = " + new SimpleHash("SHA-512", "123"));
密码加密结果:
3.3 controller层如何调用密码加密并且验证
@Component
public class DBRealm extends AuthenticatingRealm {@AutowiredUserMapper userMapper;@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken toKen) throws AuthenticationException {//当前登录的用户名和密码都在token里面保存UsernamePasswordToken usernamePasswordToken =(UsernamePasswordToken) toKen;String username = usernamePasswordToken.getUsername();Users users = userMapper.getUserByUsername(username);if (users == null){throw new UnknownAccountException("用户名输入错误");}if (!users.getEnabled()){throw new LockedAccountException("账号被锁定,登录失败");}/*传入方法的参数:1.用户登录的用户名* 2.用户的密码,注意,这个密码是从数据库查询出来的用户密码* 3.这里返回之后,系统会根据这里返回的信息,再结合用户登录时输入的用户名密码信息去判断密码是否正确* */return new SimpleAuthenticationInfo(users.getUsername(), users.getPassword(),getName());}@Overridepublic CredentialsMatcher getCredentialsMatcher() {//这里返回的是SHA-512加密方式的密码的信息摘要给数据库,所以我们要手动给数据库的password中添加,MainTest的SHA-512加密方式的信息摘要return new HashedCredentialsMatcher("SHA-512");}
3.4补充1( MD5Hash第二种加密的原因):
MD5Hash是SimpleHash的子类,所以我们也可以用SimpleHash去进行MD5的加密,但是要添加加密方式
补充2:
3.5 Shiro底层之密码如何比对
第一步:首先我们在登录界面进入token,因为我们的用户名和密码都是存储在这个token里面
第二步:
第三步:
我们controller层的方法,返回的是同一个AuthentiationInfo
第四步骤
我们来看看authenticate方法做了什么
补充: 如果我们设置了多个Realm,就要跟第六小节一样去配置多个Realm,我们这里只写了一个Realm
第五步 再进入方法
getRealms方法的作用:这个方法来进行判断我们有几个Realms,
如果有多个就进入到多个的处理逻辑,
即doMultiRealmAuthentication这个里面去
有单个就进入到单个的处理逻辑。
即doSingleRealmAuthentication这个里面去
我们这里只有一个Realm,就先进入单个处理逻辑的方法
第六步 进入单个处理逻辑doSingleRealmAuthentication
第七步:进入这个doGetAuthenticationInfo的父类
GetAuthenticationInfo看他做了什么
这样就顺利的调用到了我们的DBRealm
第八步:我们的DBrealm返回了什么呢
第九步:继续看返回了什么
9.1.得到了返回的info
9.2 这个info里包含了我们的认证信息(从数据中传出来的)
9.3 然后再把这个(后端)info和(前端)token丢入我们的cache缓存中去,这样下一次我们就不用执行这一些代码,
- info返回信息:info如果不等于Null,即我们的info是有值的话怎么返回info信息给我们的DBrealm里面的调用方法,通过assertCredentialsMatch()进行密码的比对!
要是token和info不相同的话,就去抛异常,那密码是怎么进行比对的呢?
- 进入**assertCredentialsMatch()**方法看这个方法怎么进行密码的比对
11.1 我们在我们的AuthenticatingRealm里面也就是我们的DBRealm里调用了
getCredentialsMatcher()
这是一个接口对接了我们的密码比对器(shrio默认提供的)
SimpleCredentialsMatcher这个就是默认提供给我们的密码比对器
那我们的密码比对器做了什么
12.进入密码比对器SimpleCredentialsMatcher
步骤:
1.从token中拿到用户的数据数组
2.accountcredentials中拿到用户登录的字符串
3.equal方法比较两者值是否相等
13.equals比较
4.登录验证+加密+加盐
加密+加盐方式与上面大同小异但是不同的是要多加一个参数,也是用到上面的SimpleHash或者它的子类们。
//带盐的加密字符串//第一种MD5加密方法加密,加盐Md5Hash sang = new Md5Hash("123", "sang", 1024);System.out.println("sang = " + sang);System.out.println("--------------------------------------------------");System.out.println("--------------------------------------------------");//第二种SHA-512加盐加密//加密加盐Sha512Hash sha512Hash=new Sha512Hash("123","sang",1024);System.out.println("--------------------------------------------------");SimpleHash simpleHash = new SimpleHash("SHA-512", "123", "sang", 1024);System.out.println("simpleHash = " + simpleHash);
controller调用方式与上面类似
5.RememberMe
概念:在服务端对所有的接口做一个分类,不涉及到数据修改的安全性较低的设置RememberMe
注意:RememberMe 也是一种认证的方式,不一定说所有的登录都有用账户名和密码进行登录(是便捷和用户安全之间的一种平衡)
5.1登录流程
- 登录的时候,传入用户名密码,登录成功之后,先对当前登录的用户进行序列化,序列化之后,得到一个 byte 数组,然后对这个 byte 数组进行加密(用的是 AES 对称加密,将来可以解密的),加密之后得到一个 byte 数组,但是这个 byte 数组无法直接展示出来,需要再进行一次 Base64 转码,就可以转为可读的字符串了,然后将这个字符串写入到 Cookie 中,并返回给浏览器。
5.2 验证流程
- 以后每次请求的时候,系统都会自动携带上这个 Cookie,系统收到这个 Cookie 之后,首先从请求头中提取出 RememberMe 字符串,提取出来之后首先进行 Base64 解码,解码之后,再调用 AES 服务进行解密,揭秘之后得到一个 byte 数组,再将这个 byte 数组反序列化,得到登录的用户对象。
5.3 用法
login.jsp中添加 参数
<form action="/m/doLogin" method="post"><input type="text" name="username" value="sang"><input type="password" name="password" value="123"><input type="checkbox" value="true" name="rememberMe">rememberMe<input type="submit" value="登录"></form>
LoginController
@PostMapping("/doLogin")//1.字符串传入参数(因为里面肯定带了数据所以设置为String类型)public String doLogin(String username, String password, Model model,String rememberMe) {//获取当前用户Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username, password);try {//2.登录操作之前if ("on".equals(rememberMe)){token.setRememberMe(true);}subject.login(token);return "redirect:/hello";} catch (AuthenticationException e) {e.printStackTrace();model.addAttribute("error", e.getMessage());}return "forward:/login";}
注意:
1.字符串传入参数(因为里面肯定带了数据所以设置为String类型)
2.使用密码比对器进行密码比对前,先对获取到的携带RememberMe 的数据进行判断,是否可以使用
6.配置多个Realm
6.1 使用场景:
当商家和用户登录权限相同,管理员跟上面两者权限不同的时候,用一个接口来处理商家和用户登录权限
6.2 Realm的配置
1.AtLeastOneSuccessfulStrategy (org.apache.shiro.authc.pam):至少有一个 Realm 认证成功,就算成功
2.AllSuccessfulStrategy (org.apache.shiro.authc.pam):所有 Realm 都要认证成功才算成功
3.FirstSuccessfulStrategy (org.apache.shiro.authc.pam):至少有一个 Realm 认证成功,就算成功,这个 Bean 中,有一个属性名为 stopAfterFirstSuccess,表示是否在第一个 bean 认证成功后,就不再执行后面的 Realm 了,这个属性默认为 false,即第一个 Reaml 认证成功后,后面的 Realm 还是会认证的.
此时 FirstSuccessfulStrategy 和 AtLeastOneSuccessfulStrategy 其实没有差别。
如果将 stopAfterFirstSuccess 属性设置为 true,
那么对于 FirstSuccessfulStrategy 而言,
第一个 Realm 认证成功后,后面的 Realm 就不再执行了。
<!--
这个是配置多 Realm 的认证器AtLeastOneSuccessfulStrategy (org.apache.shiro.authc.pam):至少有一个 Realm 认证成功,就算成功AllSuccessfulStrategy (org.apache.shiro.authc.pam):所有 Realm 都要认证成功才算成功FirstSuccessfulStrategy (org.apache.shiro.authc.pam):至少有一个 Realm 认证成功,就算成功,这个 Bean 中,有一个属性名为 stopAfterFirstSuccess,
表示是否在第一个 bean 认证成功后,就不再执行后面的 Realm 了,
这个属性默认为 false,
即第一个 Reaml 认证成功后,
后面的 Realm 还是会认证的,此时 FirstSuccessfulStrategy 和 AtLeastOneSuccessfulStrategy 其实没有差别。
如果将 stopAfterFirstSuccess 属性设置为 true,
那么对于 FirstSuccessfulStrategy 而言,
第一个 Realm 认证成功后,后面的 Realm 就不再执行了。
--><bean class="org.apache.shiro.authc.pam.ModularRealmAuthenticator" id="authenticator"><!--设置多个 realm --><property name="realms"><list><ref bean="DBRealm"/><ref bean="DBSaleMi"/></list></property><!--AtLeastOneSuccessfulStrategy,身份验证类--><property name="authenticationStrategy"><bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"/></property></bean><!--配置Realm-->
<!-- <bean class="com.huang.demo.realm.DBRealm" id="dbRealm"/>--><bean class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" id="securityManager"><property name="realm" ref="DBRealm"/><property name="sessionManager" ><bean class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><property name="sessionIdUrlRewritingEnabled" value="false"/></bean></property></bean><bean class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" id="shiroFilter"><property name="securityManager" ref="securityManager"/><property name="loginUrl" value="/login" /><property name="filterChainDefinitions"><!--/login=anon 表示 /login 这个路径可以匿名访问/logout=logout 后面的 logout 是注销登录过滤器的简称/**=authc 表示其余的请求,都要认证之后才能访问注意这里的顺序--><value>/logout=logout/login=anon/doLogin=anon/**=authc</value></property></bean>
7.不同的密码比对器
SimplecredentialsMatcher
密码比对器
我们通过SimplecredentialsMatcher密码比对器进行密码比对,他的下面有很多的不同的密码比对的方法。那我们改怎么使用他?
注意:小节3中的例子是没有经过加密的,所有我们可以直接去使用SimplecredentialsMatcher这个密码比对器进行密码比对,
- 但是如果我们使用了MD5进行加密。那我们就要去使用SimplecredentialsMatcher的子类Md5CredentialsMatcher()
- 注意:这个方法废弃了
- 我们使用return new HashedCredentialsMatcher(“MD5”)的方式
- 用SHA-512一样
/login=anon/doLogin=anon/**=authc</value></property>
</bean>
# 7.不同的密码比对器SimplecredentialsMatcher密码比对器[外链图片转存中...(img-azXihmGW-1657209765342)]我们通过SimplecredentialsMatcher密码比对器进行密码比对,他的下面有很多的不同的密码比对的方法。那我们改怎么使用他?> 注意:小节3中的例子是没有经过加密的,所有我们可以直接去使用SimplecredentialsMatcher这个密码比对器进行密码比对,
>
> + 但是如果我们使用了MD5进行加密。那我们就要去使用SimplecredentialsMatcher的子类Md5CredentialsMatcher()
> + 注意:这个方法废弃了
> + 我们使用return new HashedCredentialsMatcher("MD5")的方式
> + 用SHA-512一样
shiro注册登录流程(如何加密加盐)+配置多个Ream+密码加密验证底层分析+Remember使用+不同密码比对器原理(二)相关推荐
- 加解密篇 - 什么是加密加盐 (分析web3j的加盐处理)
这篇是加解密的最后一篇,来聊聊加密加盐.翻看最近的区块链钱包项目,发现 web3j 的源码中对数据做了加盐处理,正好分析一下它是如何进行加盐处理的. 目录: 什么是加盐 加盐的原理和流程 加盐 dem ...
- java加盐_Java中MD5加密加盐算法
前俩天项目组需要做一个密码的加密加盐操作,无意中在网上看到一个对应的加密加盐算法,特意在此做一个记录 import java.security.MessageDigest; import java.u ...
- BCrypt加密怎么存入数据库_Spring Boot 中密码加密的两种姿势
1.为什么要加密 2.加密方案 3.实践3.1 codec 加密3.2 BCryptPasswordEncoder 加密 4.源码浅析 先说一句:密码是无法解密的.大家也不要再问松哥微人事项目中的密码 ...
- 关于Shiro使用密码加密加盐之后序列化失败的问题(十四)
原文:https://blog.csdn.net/qq_34021712/article/details/84567437 shiro使用密码加盐之后,序列化失败 ERROR Failed to se ...
- 抖音实战~手机号密码一键注册登录流程(限制手机终端登录)
文章目录 一.手机号+密码 二.前端 2.1. 点击登陆流程 2.2. 点击登录源码 三.后端登录 3.1. 登录流程图 3.2. 流程简述 3.3. 手机号验证码登录流程 一.手机号+密码 二.前端 ...
- 密码加密 加盐 Java PBKDF2 密码哈希代码
如果你是Web开发者,你很可能需要开发一个用户账户系统.这个系统最重要的方面,就是怎样保护用户的密码.存放帐号的数据库经常成为入侵的目标,所以你必须做点什么来保护密码,以防网站被攻破时发生危险.最好的 ...
- MD5加密以及验证加密-加盐
加密与解密算法: /// <summary> /// 签名字符串 32位 /// </summary> /// <param name="input" ...
- kaggle网站注册登录流程详细介绍(小白必看)
Kaggle是一个为数据科学和机器学习提供竞赛.数据集和工具的在线平台. 该网站通过向用户提供不同领域的实际问题和数据集,吸引了全球数据科学家和机器学习从业者的关注.Kaggle还为用户提供机器学习模 ...
- 抖音实战~手机号验证码一键注册登录流程(限制手机终端登录)
文章目录 一.手机号+验证码 二.前端 2.1. 点击登陆流程 2.2. 点击登录源码 三.后端登录 3.1. 登录流程图 3.2. 流程简述 3.3. 手机号验证码登录流程 一.手机号+验证码 二. ...
- Laravel后端接口使用mews/captcha验证码注册+登录流程讲解
大致的流程讲解: 注册流程: 获取图形验证码并正确填写->请求注册验证短信->填写注册的用户信息+短信验证码->用户注册成功 登录流程: 前端请求短信->已注册用户:返回登录的 ...
最新文章
- vs2005什么时候能出正式版
- discuz 文档说明
- 修改input file默认样式
- R语言实战应用精讲50篇(三十一)-R语言入门系列-tidyverse数据分析流程
- 青少年蓝桥杯_2020_steam考试_中级组_第五题
- R语言:时间序列常用函数
- C++ 菱形虚继承 通过指针来寻找继承过来的成员变量
- 服务器系统重置,云服务器系统重置
- jsp 如何动态给图片赋值_在Excel表格中你知道如何动态引用图片吗?
- xpath的基础知识
- Enterprise Solution(2.2.20130525) 解决方案配置与源代码下载
- namp安装及官方使用手册翻译及注释5
- 传教士过河java_野人和传教士渡河问题的java实现
- iOS中WKWebView清除cookies
- 62个程序员崩溃的瞬间,你经历过了吗?哈哈哈哈哈嗝~
- 基于单片机的电压电流表设计
- Git命令及集成IDEA、Gitee/GitHub/GitLab
- 高中信息技术c语言编程题,高中信息技术招聘C语言编程题精选.doc
- 使用python批量下载天猫数据并进行合并(非爬虫)
- 计算机专业术语简单释义
热门文章
- 义嘉泰带你了解环境光和接近传感器
- 债券数据集:绿色债券数据集、历时新发、发行债券、DCM定价估值四大指标数据
- 李沐老师 PyTorch版——线性回归 + softmax回归的简洁实现(3)
- 读 PHP - Pimple 源码笔记(下)
- Maven原始setting.xml文件备份
- 扫雷算法实现(简易版,只能在CMD指令中玩)
- SpringSecurityOAuth2.0获取Token时报错Encoded password does not look like BCrypt
- 【原创】自制操作系统知识储备(一)---流程篇
- 国内期市前7个月成交超去年全年
- antv g2字体阴影_antv g2 notes