Spring security 密码加密使用

news2024/11/15 9:57:18

一、密码加密

    2011年12月21日,有人在网络上公开了一个包含600万个CSDN 用户资料的数据库,数据全部为明文储存,包含用户名、密码以及注册邮箱。事件发生后CSDN 在微博、官方网站等渠道发出了声明、解释说此数据库系2009 年备份所用,因不明原因泄漏,已经向警方报案,后又在官网发出了公开道歉信。在接下来的十多天里,金山,网易,京东、当当、新等多家公司被卷入到这次事件中。整个事件中最触目惊心的莫过于CSDN把用户密码明文存储,由于很多用户是多个网站共用一个密码,因此一个网站密码泄漏就会造成很大的安全患。由于有了这么多前车之鉴、我们现在做系统时,密码都要加密处理。

在前面的案例中,凡是涉及密码的地方,我们都采用明文存储,在实际项目中这肯定是不可取的,因为这会带来极高的安全风险。在企业级应用中,密码不仅需要加密,还需要加大程度地保证密码安全,防止用户信息泄露;

二、密码加密的常见方案

   2.1.1 Hash 算法

    最早我们使用类似 SHA-256、SHA-512、MD5等这样的单向 Hash 算法。用户注册成功后,保存在数据库中不再是用户的明文密码,而是经过 SHA-256 加密计算的一个字行串当用户进行登录时,用户输入的明文密码用SHA-256 进行加密,加密完成之后,再和存储在数据库中的密码进行比对,进而确定用户登录信息是否有效。如果系统遭遇攻击,最多也只是存储在数据库中的密文被泄漏。

这样就绝对安全了吗?由于彩表这种攻击方式的存在以及随着计算机硬件的发展,每利执行数十亿次 HASH计算已经变得轻轻松松,这意味着即使给密码加密加盐也不再安全;

2.1.2 单向自适应函数

   在Spring Security 中,我们现在是用一种自适应单向函数(Adaptive One-way Functions)来处理密码问题,这种自适应单向函数在进行密码匹配时,会有意占用大量系统资源(例如CPU、内存等),这样可以增加恶意用户攻击系统的难度。在Spring Securiv 中,开发者可以通过bcrypt、PBKDF2、sCrvpt以及argon2 来体验这种自适应单向函数加密。由于自适应单向函数有意占用大量系统资源,因此每个登录认证请求都会大大降低应用程序的性能,作是SpringSecuity不会采取任何措施来提高密码验证速度,因为它正是通过这种方式来增强系统的安全性。

三、PasswordEncoder 密码加密器

Spring Security的PasswordEncoder接口用于执行密码的单向转换,以允许安全地存储密码。鉴于PasswordEncoder是一种单向转换,当密码转换需要双向转换时(即存储用于向数据库进行身份验证的凭据),就不打算这样做。通常,PasswordEncoder用于存储在身份验证时需要与用户提供的密码进行比较的密码。

3.1 BCryptPasswordEncoder

   BCryptPasswordEncoder使用 bcrypt 算法对密码进行加密,为了提高密码的安全性,bcrypt算法故意降低运行速度,以增强密码破解的难度。同时 BCryptP asswordEncode“为自己带盐”开发者不需要额外维护一个“盐”字段,使用BCryptPasswordEncoder 加密后的字符串就已经“带盐”了,即使相同的明文每次生成的加密字符串都不相同。

3.2 Argon2PasswordEncoder

  Argon2PasswordEncoder 使用Argon2 算法对密码进行加密,Argon2 曾在 PassworHashing Competition 竞赛中获胜。为了解决在定制硬件上密码容易被破解的问题Argon2也是故意降低运算速度,同时需要大量内存,以确保系统的安全性。

3.3 Pbkdf2PasswordEncoder

  Pbkdf2PasswordEncoder使用PBKDF2算法对密码进行加密和前面几种类似,PBKDF2算法也是一种故意降低运算速度的算法,当需要FIPS(Federal Information ProcessingStandard美国联邦信息处理标准)认证时,PBKDF2 算法是一个很好的选择。

3.4 SCryptPasswordEncoder

  SCryptPasswordEncoder 使用scrypt 算法对密码进行加密,和前面的几种类似,serypt也是一种故意降低运算速度的算法,而且需要大量内存。

3.5 默认的几种加密方式

@Test

public void test() f

//1 .BCryptPasswordEncoder

BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder()

System.out.println(bCryptPasswordEncoder.encode( "123"));

//2.Pbkdf2PasswordEncode

Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder()

System.out.println(pbkdf2PasswordEncoder.encode("123"));

//3.SCryptPasswordEncoder //需要额外引入依赖

SCryptPasswordEncoder sCryptPasswordEncoder = new SCryptPasswordEncoder()

System.out.println(sCryptPasswordEncoder.encode("123")):

1/4.Argon2PasswordEncoder //需要额外入依邮

Argon2PasswordEncoder argon2PasswordErcoder = new Argon2PasswordEncoder():

System.out.println(argon2PasswordEncoder.encode("123"));

}


四、DelegatingPasswordEncoder 密码加密器代理

   在Spring Security 5.0之前,默认的PasswordEncoder是NoOpPasswordEncoder,它需要纯文本密码。根据密码历史部分,您可能会认为默认的PasswordEncoder现在类似于BCryptPasswordEncoder。然而,这忽略了三个现实世界的问题:

1、有许多使用旧密码编码的应用程序无法轻松迁移

2、密码存储的最佳做法将再次更改

3、作为一个框架,Spring Security不能频繁进行破坏性更改

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

1、确保使用当前的密码存储建议对密码进行编码

2、允许验证现代和传统格式的密码

3、允许将来升级编码

4.1 创建一个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", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());

PasswordEncoder passwordEncoder =
new DelegatingPasswordEncoder(idForEncode, encoders);

4.2 为什么在密码前面加上{noop}其他前缀就可以匹配

 4.2.1 源码部分:WebSecurityConfigurerAdapter

总结:通过源码我们看到当我们加上了noop 最后会调用NoOpPasswordEncoder 实现,直接通过equals 判断,直接字符串比较得到是否相等

4.3.2 密码在何处使用

总结: 通过源码分析得知如果在工厂中指定了PasswordEncoder,就会使用指定PasswordEncoder.  否则就会使用默认DelegatingPasswordEncoder。


五、如何使用 PasswordEncoder

我们可以使用动态配置和固定配置两种模式,默认就是动态配置模式,什么都不写

5.1 使用动态密码配置

实际上就写自己的加密方式,不要手动创建 PasswordEncoder 的bean对象就可以了

@SpringBootTest
public class SecurityConfigurationTest {


    @Test
    public void userDetailsService() {
        Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
        String encode = encoder.encode("123456");
        System.out.println(encode);

    }
}
得到密码:b694b853c2a55717df36e90fd46dae9bbaad46461f9c8bcc3564ef06908e77400f35f3184c11150d

    /**
     *  自定义数据源
     * @return
     */
    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
        userDetailsManager.createUser(User.withUsername("test").password("{pbkdf2}b694b853c2a55717df36e90fd46dae9bbaad46461f9c8bcc3564ef06908e77400f35f3184c11150d").authorities("admin").build());
        return userDetailsManager;
}

5.1.1 测试登录是否能匹配

5.2 使用固定密码加密方案

系统使用指定的某一种加密方案,不基于动态配置

5.2.1 注入加密编码器

 @Bean
    public PasswordEncoder passwordEncoder() {
        return new Pbkdf2PasswordEncoder();
}

5.2.2 去掉密码的前缀 {pbkdf2}

 /**
     *  自定义数据源
     * @return {pbkdf2}
     */
    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
        userDetailsManager.createUser(User.withUsername("test").password("b694b853c2a55717df36e90fd46dae9bbaad46461f9c8bcc3564ef06908e77400f35f3184c11150d").authorities("admin").build());
        return userDetailsManager;
    }

5.2.3 源码实现


六、密码自动升级

spring security 基于安全考虑,设计了一套能自动进行升级的配置,只需要实现UserDetailsPasswordService 就会更新

通过源码分析我们得知,需要实现UserDetailsPasswordService 方法,而且密码必须是{noop}12345 这种模式

6.1 代码配置

@Bean
public UserDetailsService userDetailsService() {
    InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
    userDetailsManager.createUser(User.withUsername("test").password("{noop}12345").authorities("admin").build());
    return userDetailsManager;
}

6.2 源码

更新后,将user密码重新赋值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2080412.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网易大数据模型

网易大数据平台 https://sf.163.com/

番茄叶部病害-目标检测数据集(包括VOC格式、YOLO格式)

番茄叶部病害-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1hZdoXcYEcJaw9spazrxGZg?pwdtsaw 提取码&#xff1a;tsaw 数据集信息介绍&#xff1a; 共有 534 张图像和一一对应的标注文件 标…

【Kotlin设计模式】Kotlin实现外观模式

前言 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;旨在为子系统中的一组接口提供一个统一的接口。外观模式定义了一个高层接口&#xff0c;使得这一子系统更加容易使用。它将复杂的子系统封装在一个简单的接口后面&#xff0c;从而降低了客…

边缘物联网平台AIoTedge推荐

AIoTedge是一个创新的智能边缘计算平台&#xff0c;它通过边云协同的架构设计&#xff0c;实现了多点部署和分布式计算&#xff0c;提高了数据处理的速度和效率&#xff0c;同时确保了数据的安全性和隐私性。平台具备强大的分布式AIoT处理能力&#xff0c;适用于多种场景&#…

移动端+PC端源码,智慧城管执法系统,后端框架:springboot,移动端:uniapp

市管理综合执法管理平台实现执法办案、业务全流程在线办理&#xff0c;依托移动端PC端的“两端”应用模式&#xff0c;保障能够通过信息化手段进行日常的执法办案工作&#xff0c;强化执法监督功能。提供了案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析等功能&…

2024-如何在低版本Mac OS安装合适的xcode-详细的技术篇

2024-如何在低版本Mac OS安装合适的xcode-详细的技术篇 1. 最烦人的是我不想升降我的macos系统&#xff0c;但是我是一名程序猿我想要玩IOS开发&#xff0c;那就需要下载对应的XCode的编译器。就会出现下面的情况&#xff1f;&#xff1f; 就会出现这样子的情况 原因是我的版…

算法-容斥原理

venn图&#xff1a; 如何求三个圆圈的面积之和&#xff1f; 此时&#xff0c;||不代表绝对值&#xff0c;代表集合的个数 解题思路&#xff1a; 实际上&#xff0c;我们不需要知道每个集合中的元素具体是什么&#xff0c;只需要知道每个集合的大小 例如 &#xff0c;表示10以…

物联网通讯协议MQTT、NB-IOT、Zigbee、CoAP、RFID、BLUETOOTH、NFC、4G和HTTP

物联网协议集 一、按网络四层协议分类 NB-IoT&#xff0c;LORA&#xff0c;WIFI&#xff0c;蓝牙&#xff0c;zigbee&#xff0c;4G都是物理层的&#xff0c;这几个都需要芯片模组支持&#xff08;硬件支持&#xff09; 而MQTT&#xff0c;COAP&#xff0c;HTTP都是应用层协议…

Web入门-05.HTTP协议-响应协议

一.HTTP响应协议的格式 与客户端向服务器发送的HTTP请求(仅指POST请求)格式类似&#xff0c;服务器向客户端发送的HTTP相应格式也分为三类&#xff0c;响应行&#xff0c;响应头和响应体。 HTTP/1.1 200 OK 响应行&#xff1a;响应数据第一行&#xff08;协议、状态码、…

风水学本质上是人机环境系统工效学

风水学与人机环境系统工效学的关系可以这样理解&#xff1a; 风水学源于传统文化&#xff0c;关注如何通过环境布局和方位来促进个人的健康、运势和幸福。它强调环境与个人之间的和谐&#xff0c;试图通过调整环境来提升生活质量。 而人机环境系统工效学则是基于现代科学&#…

面试题每日一练,测测你对JavaScript WeakMap 和数组方法的理解

今天的挑战题目涉及到JavaScript中的 WeakMap、数组方法 map 和 reduce&#xff0c;以及对对象引用的管理。让我们一步步解析这段代码&#xff0c;看看它会输出什么以及为什么。 代码解析 首先&#xff0c;代码创建了一个 WeakMap 实例&#xff1a; const weakMap new WeakMap…

Maven Wrapper深入实战

概述 官网&#xff0c;GitHub。 Maven Wrapper&#xff0c;缩写为mvnw&#xff0c;是一个受Gradle Wrapper和Takari Wrapper启发而产生的Maven子项目&#xff0c;主要有以下三个用途&#xff1a; 让开发者电脑上无需安装Maven&#xff0c;也不用配置环境变量&#xff0c;即可…

Java面试宝典-java基础02

Java面试宝典-java基础02 11、使用 final 关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?12、this 和super 关键字的作用13、在 Java 中,为什么不允许从静态方法中访问非静态变量?14、final 与 static 的区别?15、int可以强制转换为byte吗?16、char 型变量中…

安卓中synchronized 关键字 的作用和介绍

在Java中&#xff0c;synchronized 关键字用于控制多线程环境下对方法或代码块的访问&#xff0c;确保在同一时刻只有一个线程可以执行该方法或代码块。当你在方法声明中使用 synchronized 关键字&#xff0c;这意味着任何线程在调用该方法之前必须获得该方法所属对象的锁。这通…

Android Abort message: ‘Error, cannot access an invalid/free‘d bitmap here!‘

Android Abort message: Error, cannot access an invalid/freed bitmap here! Error, cannot access an invalid/freed bitmap here 在某些Glide加载场景中&#xff0c;如果Glide把Bitmap加载放入到view后&#xff0c;又去从view里面取Bitmap&#xff0c;会抛上述NE错误。 解…

代码随想录 刷题记录-18 动态规划(2)01背包问题、习题

一、01背包理论基础 例题&#xff1a;46. 携带研究材料 01 背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 暴力解法&#xff1a…

大模型实战-FinGLM解析金融财报做RAG经验参考篇

大模型实战-FinGLM金融财报解析实战 https://modelscope.cn/datasets/modelscope/chatglm_llm_fintech_raw_dataset/summary 详细解读&#xff1a; https://modelscope.cn/models/finglm/FinGLM/summary 背景&#xff1a;解读pdf版本的公司财务年报&#xff0c;构建问答模型…

zsh: command not found: brew(M系列芯片)

利用官网的命令安装完brew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"查看版本&#xff0c;提示找不到命令 % brew -v zsh: command not found: brew解决方法&#xff0c;在终端中执行以下命令&#xff0c…

EV代码签名证书——消除软件下载时的安全警告

开发公司和软件开发人员在发布应用程序后&#xff0c;当用户尝试下载并安装应用程序时&#xff0c;被SmartScreen识别为不常见或尚未建立起良好的信誉度&#xff0c;系统就会发出警告&#xff0c;提示用户该应用程序可能对电脑构成风险。这会导致软件下载率大幅度下降。 EV代码…

鸿蒙XComponent组件的认识

概述&#xff1a; XComponent组件作为一种渲染组件&#xff0c;通常用于满足开发者较为复杂的自定义渲染需求&#xff0c;例如相机预览流的显示、游戏画面的渲染、自定义视频播放器等等。其中Native API是其核心内容&#xff01; 其可通过指定其type字段来实现不同的功能&…