1.注册

1.1 注册流程

  1. 用户输入用户名密码进行注册。

  2. 服务端收到用户名密码之后,进行一个加密处理,然后再存到数据库中。

    //带盐的加密字符串
    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 登录流程

  1. 登录的时候用户输入用户名密码。
  2. 登录时候,主要在 com.qfedu.demo.realm.DbRealm#doGetAuthenticationInfo 方法中处理登录逻辑,这个方法主要是根据登录用户名去数据库查询到用户信息,并返回。
  3. 系统会自动调用 com.qfedu.demo.realm.DbRealm#getCredentialsMatcher 方法中提供的密码比对器,做最后的密码比对操作。

3.登录加密验证

3.1数据库

我们这里设置六个字段

  1. id 用户id
  2. username用户名 —>以后都是用用户名进行加盐操作
  3. password用户密码—> 密码以后要进行加密,有两种加密方法
    1. MD5
    2. SHA-512
  4. nickname暂时用不到
  5. 权限名(boolean类型)1,0
  6. 用户权限类型

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缓存中去,这样下一次我们就不用执行这一些代码,

  1. info返回信息:info如果不等于Null,即我们的info是有值的话怎么返回info信息给我们的DBrealm里面的调用方法,通过assertCredentialsMatch()进行密码的比对!

要是token和info不相同的话,就去抛异常,那密码是怎么进行比对的呢?

  1. 进入**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登录流程

  1. 登录的时候,传入用户名密码,登录成功之后,先对当前登录的用户进行序列化,序列化之后,得到一个 byte 数组,然后对这个 byte 数组进行加密(用的是 AES 对称加密,将来可以解密的),加密之后得到一个 byte 数组,但是这个 byte 数组无法直接展示出来,需要再进行一次 Base64 转码,就可以转为可读的字符串了,然后将这个字符串写入到 Cookie 中,并返回给浏览器。

5.2 验证流程

  1. 以后每次请求的时候,系统都会自动携带上这个 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使用+不同密码比对器原理(二)相关推荐

  1. 加解密篇 - 什么是加密加盐 (分析web3j的加盐处理)

    这篇是加解密的最后一篇,来聊聊加密加盐.翻看最近的区块链钱包项目,发现 web3j 的源码中对数据做了加盐处理,正好分析一下它是如何进行加盐处理的. 目录: 什么是加盐 加盐的原理和流程 加盐 dem ...

  2. java加盐_Java中MD5加密加盐算法

    前俩天项目组需要做一个密码的加密加盐操作,无意中在网上看到一个对应的加密加盐算法,特意在此做一个记录 import java.security.MessageDigest; import java.u ...

  3. BCrypt加密怎么存入数据库_Spring Boot 中密码加密的两种姿势

    1.为什么要加密 2.加密方案 3.实践3.1 codec 加密3.2 BCryptPasswordEncoder 加密 4.源码浅析 先说一句:密码是无法解密的.大家也不要再问松哥微人事项目中的密码 ...

  4. 关于Shiro使用密码加密加盐之后序列化失败的问题(十四)

    原文:https://blog.csdn.net/qq_34021712/article/details/84567437 shiro使用密码加盐之后,序列化失败 ERROR Failed to se ...

  5. 抖音实战~手机号密码一键注册登录流程(限制手机终端登录)

    文章目录 一.手机号+密码 二.前端 2.1. 点击登陆流程 2.2. 点击登录源码 三.后端登录 3.1. 登录流程图 3.2. 流程简述 3.3. 手机号验证码登录流程 一.手机号+密码 二.前端 ...

  6. 密码加密 加盐 Java PBKDF2 密码哈希代码

    如果你是Web开发者,你很可能需要开发一个用户账户系统.这个系统最重要的方面,就是怎样保护用户的密码.存放帐号的数据库经常成为入侵的目标,所以你必须做点什么来保护密码,以防网站被攻破时发生危险.最好的 ...

  7. MD5加密以及验证加密-加盐

    加密与解密算法: /// <summary> /// 签名字符串 32位 /// </summary> /// <param name="input" ...

  8. kaggle网站注册登录流程详细介绍(小白必看)

    Kaggle是一个为数据科学和机器学习提供竞赛.数据集和工具的在线平台. 该网站通过向用户提供不同领域的实际问题和数据集,吸引了全球数据科学家和机器学习从业者的关注.Kaggle还为用户提供机器学习模 ...

  9. 抖音实战~手机号验证码一键注册登录流程(限制手机终端登录)

    文章目录 一.手机号+验证码 二.前端 2.1. 点击登陆流程 2.2. 点击登录源码 三.后端登录 3.1. 登录流程图 3.2. 流程简述 3.3. 手机号验证码登录流程 一.手机号+验证码 二. ...

  10. Laravel后端接口使用mews/captcha验证码注册+登录流程讲解

    大致的流程讲解: 注册流程: 获取图形验证码并正确填写->请求注册验证短信->填写注册的用户信息+短信验证码->用户注册成功 登录流程: 前端请求短信->已注册用户:返回登录的 ...

最新文章

  1. vs2005什么时候能出正式版
  2. discuz 文档说明
  3. 修改input file默认样式
  4. R语言实战应用精讲50篇(三十一)-R语言入门系列-tidyverse数据分析流程
  5. 青少年蓝桥杯_2020_steam考试_中级组_第五题
  6. R语言:时间序列常用函数
  7. C++ 菱形虚继承 通过指针来寻找继承过来的成员变量
  8. 服务器系统重置,云服务器系统重置
  9. jsp 如何动态给图片赋值_在Excel表格中你知道如何动态引用图片吗?
  10. xpath的基础知识
  11. Enterprise Solution(2.2.20130525) 解决方案配置与源代码下载
  12. namp安装及官方使用手册翻译及注释5
  13. 传教士过河java_野人和传教士渡河问题的java实现
  14. iOS中WKWebView清除cookies
  15. 62个程序员崩溃的瞬间,你经历过了吗?哈哈哈哈哈嗝~
  16. 基于单片机的电压电流表设计
  17. Git命令及集成IDEA、Gitee/GitHub/GitLab
  18. 高中信息技术c语言编程题,高中信息技术招聘C语言编程题精选.doc
  19. 使用python批量下载天猫数据并进行合并(非爬虫)
  20. 计算机专业术语简单释义

热门文章

  1. 义嘉泰带你了解环境光和接近传感器
  2. 债券数据集:绿色债券数据集、历时新发、发行债券、DCM定价估值四大指标数据
  3. 李沐老师 PyTorch版——线性回归 + softmax回归的简洁实现(3)
  4. 读 PHP - Pimple 源码笔记(下)
  5. Maven原始setting.xml文件备份
  6. 扫雷算法实现(简易版,只能在CMD指令中玩)
  7. SpringSecurityOAuth2.0获取Token时报错Encoded password does not look like BCrypt
  8. 【原创】自制操作系统知识储备(一)---流程篇
  9. 国内期市前7个月成交超去年全年
  10. antv g2字体阴影_antv g2 notes