首页 > 其他分享 >springboot3 security 从始至终--02 PasswordEncoder

springboot3 security 从始至终--02 PasswordEncoder

时间:2023-02-08 00:22:05浏览次数:48  
标签:02 encoders -- PasswordEncoder 密码 put encoded password

接下来几个章节,将逐个介绍身份验证流程中主要接口

接口 描述
UserDetails 代表SpringSecurity所看到的用户
GrantedAuthority 定义应用程序目的范围内允许用户执行的操作(读、写、删除等)
UserDetailsService 表示用于按用户名检索用户详细信息的对象
UserDetailsManager 一个较为特殊的UserDetailsService接口。除了按用户名检索用户外,它还可以用于更改用户集合或特定用户
PasswordEncoder 指定如何对密码进行加密或哈希化,以及检查给定的已编码字符串是由与明文密码匹配

本文将一起学习相对独立的PasswordEncoder。

一、先看看定义

package org.springframework.security.crypto.password;

/**
 * Service interface for encoding passwords.
 *
 * The preferred implementation is {@code BCryptPasswordEncoder}.
 *
 * @author Keith Donald
 */
public interface PasswordEncoder {

	/**
	 * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
	 * greater hash combined with an 8-byte or greater randomly generated salt.
	 */
	String encode(CharSequence rawPassword);

	/**
	 * Verify the encoded password obtained from storage matches the submitted raw
	 * password after it too is encoded. Returns true if the passwords match, false if
	 * they do not. The stored password itself is never decoded.
	 * @param rawPassword the raw password to encode and match
	 * @param encodedPassword the encoded password from storage to compare with
	 * @return true if the raw password, after encoding, matches the encoded password from
	 * storage
	 */
	boolean matches(CharSequence rawPassword, String encodedPassword);

	/**
	 * Returns true if the encoded password should be encoded again for better security,
	 * else false. The default implementation always returns false.
	 * @param encodedPassword the encoded password to check
	 * @return true if the encoded password should be encoded again for better security,
	 * else false.
	 */
	default boolean upgradeEncoding(String encodedPassword) {
		return false;
	}

}

该接口定义了两个抽象方法,其中几个具有默认实现。在处理PasswordEncoder实现时,最常见的是抽象的encode()和matches()方法。

encode(CharSequence rawPassword)方法的目的是返回所提供字符串的转换。就SpringSecurity功能而言,它用于为指定密码提供加密或哈希化。

之后可以使用matches(CharSequence rawPassword, String encodedPassword)方法检查已编码的字符串是否与演示密码匹配。可以在身份验证过程中使用matches()方法根据一组已知凭据来检验所提供的的密码。

第三个方法被称为upgradeEncoding(String encodedPassword),在接口中默认设置为false。如果重写它以返回true,那么为了更好的安全性,将重新对已编码的密码进行编码(不推荐这种方式)。

二、接口的作用

一般而言,系统并不以明文形式管理密码,因此密码通常要经过某种转换,这使得读取和窃取密码变得较为困难。为此,SpringSecurity定义了一个单独的接口。

实现这个接口是为了告知SpringSecurity如何验证用户的密码。在身份验证过程中,PasswordEncoder会判定密码是否有效。每个系统都会存储以某种方式编码过的密码。最好把密码哈希化存储起来,这样别人就不会读到明文密码了。PasswordEncoder还可以对密码进行编码。接口声明的encode()和matches()方式实际上是对其职责的定义。这两个方法都是同一接口的一部分,因此它们紧密相连。应用程序对密码进行编码的方式与验证密码的方式相关。

三、实现PasswordEncoder

3.1 使用默认的PasswordEncoder

在 Spring Security 5.0 之前,PasswordEncoder 默认值是 NoOpPasswordEncoder,这需要纯文本密码。 但现在您可能期望现在的默认值类似于BCryptPasswordEncoder。但是,这忽略了三个现实世界的问题:

  • 许多应用程序使用无法轻松迁移的旧密码编码。
  • 密码存储的最佳做法将再次更改。
  • 作为一个框架,Spring 安全性不能经常进行重大更改。

相反,Spring Security 引入了 DelegatingPasswordEncoder,它通过以下方式解决了所有问题:

  • 确保使用当前密码存储建议对密码进行编码
  • 允许以现代和传统格式验证密码
  • 允许将来升级编码

您可以使用PasswordEncoderFactories轻松构造DelegatingPasswordEncoder 的实例:

PasswordEncoder passwordEncoder =  
   PasswordEncoderFactories.createDelegatingPasswordEncoder();

当然也可以选择其它实例:

String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
encoders.put("pbkdf2@SpringSecurity_v5_8", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("sha256", new StandardPasswordEncoder());

PasswordEncoder passwordEncoder =
    new DelegatingPasswordEncoder(idForEncode, encoders);

3.2 使用自定义的的PasswordEncoder

通常情况下,使用spring boot security自带的password encoder已经足够满足使用场景了。笔者也不建议自己实现password encoder。

3.3 注入PasswordEncoder

在开发中,我们将 BCryptPasswordEncoder 的实例放入Spring容器即可

//密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

标签:02,encoders,--,PasswordEncoder,密码,put,encoded,password
From: https://www.cnblogs.com/zhouXX/p/17097114.html

相关文章

  • 2023.2.7
    ObjectOutputStreamObjectInputStream序列化(Serialize)java对象存储到文件中,将java对象的状态保存下来的过程参与序列化和反序列化的必须implmentsSerializable接口......
  • BUUCTF Java逆向解密 RE
    Java逆向,百度一下采用Jadx-gui打开后得到如下代码packagedefpackage;importjava.util.ArrayList;importjava.util.Scanner;/*renamedfrom:Reversereason:d......
  • 发送post请求,鼠标移入显示内容
    <!DOCTYPEhtml><html> <head> <metacharset="utf-8"> <title> </title> <style> #result{ width:300px; height:100px; border:1pxsolid......
  • java创建线程的方式有几种?
    java中创建线程的方式有多少种,这个问题也是众多纷纭,这个时候更应该参考官方文档(https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html)了,文档很明确地指出......
  • 后端发出请求,前端进行接收(AJAX)
    <!DOCTYPEhtml><html> <head> <metacharset="utf-8"> <title></title> <style> #result{ width:300px; height:100px; border:1pxsolidred;......
  • 第 1,2 课、环境搭建-Python+Selenium+pycharm
                          ......
  • vins-fusion(2)VINS-Fusion修改EVO的评测与使用
    https://blog.csdn.net/qq_38364548/article/details/123669506 2.EVO安装详细的安装过程见我的另一篇博客Ubuntu18.04———VIO算法评测工具EVO的安装与使用 6......
  • Day4——分支与循环
    分支与循环语句if条件语句:if(判断条件)…elseif(条件二)… ……elsewhile循环语句: while(条件)  { }for循环:for(初始值;条件句;调整值)switch分支语句:switch......
  • Linux 目录的可执行权限的含义
    总所周知:Linux的文件和目录的权限,只有RWX三种。r(Read,读取)对于文件:具有读取文件内容的权限对于目录:具有浏览目录的权限w(Write,写入)对于文件:具有新增,修改,删除文......
  • ChatGPT 怎么用最新详细教程
    ChatGPT以其强大的信息整合和对话能力惊艳了全球,在自然语言处理上面表现出了惊人的能力。这么强大的工具我们都想体验一下,那么 ChatGPT 怎么用呢?本文将给你逐步详细介......