Spring Security 05 密码加密

news/2024/9/17 15:53:41/

目录

DelegatingPasswordEncoder

使用 PasswordEncoder

密码加密实战

密码自动升级


实际密码比较是由PasswordEncoder完成的,因此只需要使用PasswordEncoder 不同实现就可以实现不同方式加密。

public interface PasswordEncoder {// 进行明文加密String encode(CharSequence rawPassword);
​// 比较密码boolean matches(CharSequence rawPassword, String encodedPassword);
​// 密码升级default boolean upgradeEncoding(String encodedPassword) {return false;}
}

DelegatingPasswordEncoder

根据上面 PasswordEncoder的介绍,可能会以为 Spring security 中默认的密码加密方案应该是四种自适应单向加密函数中的一种,其实不然,在 spring Security 5.0之后,默认的密码加密方案其实是 DelegatingPasswordEncoder。从名字上来看,DelegatingPaswordEncoder 是一个代理类,而并非一种全新的密码加密方案,DeleggtinePasswordEncoder 主要用来代理上面介绍的不同的密码加密方案。为什么采DelegatingPasswordEncoder 而不是某一个具体加密方式作为默认的密码加密方案呢?主要考虑了如下两方面的因素:

  • 兼容性:使用 DelegatingPasswrordEncoder 可以帮助许多使用旧密码加密方式的系统顺利迁移到 Spring security 中,它允许在同一个系统中同时存在多种不同的密码加密方案。
  • 便捷性:密码存储的最佳方案不可能一直不变,如果使用 DelegatingPasswordEncoder作为默认的密码加密方案,当需要修改加密方案时,只需要修改很小一部分代码就可以实现。

DelegatingPasswordEncoder源码

public class DelegatingPasswordEncoder implements PasswordEncoder {....
}

PasswordEncoderFactories源码

public final class PasswordEncoderFactories {
​private PasswordEncoderFactories() {}
​@SuppressWarnings("deprecation")public static PasswordEncoder createDelegatingPasswordEncoder() {String encodingId = "bcrypt";Map<String, PasswordEncoder> encoders = new HashMap<>();encoders.put(encodingId, new BCryptPasswordEncoder());encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());encoders.put("scrypt", new SCryptPasswordEncoder());encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));encoders.put("SHA-256",new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());encoders.put("argon2", new Argon2PasswordEncoder());return new DelegatingPasswordEncoder(encodingId, encoders);}
​
}

使用 PasswordEncoder

查看WebSecurityConfigurerAdapter类中源码

static class LazyPasswordEncoder implements PasswordEncoder {private ApplicationContext applicationContext;private PasswordEncoder passwordEncoder;
​LazyPasswordEncoder(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}
​public String encode(CharSequence rawPassword) {return this.getPasswordEncoder().encode(rawPassword);}
​public boolean matches(CharSequence rawPassword, String encodedPassword) {return this.getPasswordEncoder().matches(rawPassword, encodedPassword);}
​public boolean upgradeEncoding(String encodedPassword) {return this.getPasswordEncoder().upgradeEncoding(encodedPassword);}
​private PasswordEncoder getPasswordEncoder() {if (this.passwordEncoder != null) {// 若指定的 passwordEncoder 不为空则使用指定的 passwordEncoderreturn this.passwordEncoder; } else {// 使用默认的 DelegatingPasswordEncoderPasswordEncoder passwordEncoder = (PasswordEncoder)AuthenticationConfiguration.getBeanOrNull(this.applicationContext, PasswordEncoder.class);if (passwordEncoder == null) {passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();}
​this.passwordEncoder = passwordEncoder;return passwordEncoder;}}
​public String toString() {return this.getPasswordEncoder().toString();}}

密码加密实战

    @Beanpublic PasswordEncoder BcryptPasswordEncoder(){return new BCryptPasswordEncoder();}
​@Beanpublic UserDetailsService userDetailsService(){UserDetails user = User.withUsername("admin").password("$2a$10$WGFkRsZC0kzafTKOPcWONeLvNvg2jqd3U09qd5gjJGSHE5b0yoy6a").roles("ADMIN").build();return new InMemoryUserDetailsManager(user);}

使用灵活密码加密方案 推荐

    @Beanpublic UserDetailsService userDetailsService(){UserDetails user = User.withUsername("admin").password("$2a$10$WGFkRsZC0kzafTKOPcWONeLvNvg2jqd3U09qd5gjJGSHE5b0yoy6a").roles("ADMIN").build();return new InMemoryUserDetailsManager(user);}

密码自动升级

@Mapper
public interface UserMapper {
​//根据用户名查询用户User loadUserByUsername(String username);
​Integer updatePassword(@Param("username") String username, @Param("password") String password);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yang.mapper.UserMapper">
​<update id="updatePassword">update `user` set password = #{password}where username= #{username}</update>
​<!--查询单个--><select id="loadUserByUsername" resultType="com.yang.entity.User">select id,username,password,enabled,accountNonExpired,accountNonLocked,credentialsNonExpiredfrom userwhere username = #{username}</select>
​
</mapper>
public interface UserService {
​UserDetails loadUserByUsername(String username);
​Integer updateUser(String username, String password);
}
@Service
public class UserServiceImpl implements UserService {
​private final UserMapper userMapper;
​@Autowiredpublic UserServiceImpl(UserMapper userMapper) {this.userMapper = userMapper;}
​@Overridepublic UserDetails loadUserByUsername(String username) {User user = userMapper.loadUserByUsername(username);if(ObjectUtils.isEmpty(user)){throw new RuntimeException("用户不存在");}user.setRoles(userMapper.getRolesByUid(user.getId()));return user;}
​@Overridepublic Integer updateUser(String username, String password) {return userMapper.updatePassword(username, password);}
}
@Component
public class UserDetailService implements UserDetailsService, UserDetailsPasswordService {
​private final UserService userService;
​public UserDetailService(UserService userService) {this.userService = userService;}
​@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {return userService.loadUserByUsername(username);}
​@Overridepublic UserDetails updatePassword(UserDetails user, String newPassword) {Integer updateRow = userService.updateUser(user.getUsername(), newPassword);if (updateRow == 1){((User) user).setPassword(newPassword);}return user;}
}
@Configuration
public class WebSecurityConfig {
​private final UserDetailService userDetailService;
​public WebSecurityConfig(UserDetailService userDetailService) {this.userDetailService = userDetailService;}
​@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {return authenticationConfiguration.getAuthenticationManager();}
​
​@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests().mvcMatchers("/index").permitAll().anyRequest().authenticated().and().formLogin().and().userDetailsService(userDetailService); // 自定义数据源return http.csrf().disable().build();}
}


http://www.ppmy.cn/news/47960.html

相关文章

AI大模型加速RPAxAI时代到来,谁会是RPA领域的杀手级应用?

GPT等AI大模型震撼来袭&#xff0c;基于RPA的超级自动化仍是最佳落地载体 对话弘玑CPO贾岿&#xff0c;深入了解国产RPA厂商对AI大模型的探索与实践 文/王吉伟 关于RPA已死的说法&#xff0c;在中国RPA元年&#xff08;2019年&#xff09;投资机构疯狂抢项目之时就已经有了。…

西北乱跑娃 -- centos7安装python3.8最全教程

Centos7安装Python3.8详细教程 安装编译相关工具 yum -y groupinstall "Development tools" yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel yum install …

java 内置锁

java 内置锁 1.java内置锁是一个互斥锁&#xff0c;也就说明最多只有一个线程能够获得该锁&#xff0c;当线程A获得锁时&#xff0c;线程B想要尝试获得锁的时候&#xff0c;必须等线程A释放锁&#xff0c;若线程A一直不释放锁&#xff0c;则线程B一直等待处于阻塞状态中。获取…

Java锁的区别:独占模式与共享模式

目录 前言&#xff1a; Java 独占模式的锁有哪些&#xff1f; 共享模式的锁有哪些&#xff1f; Java即是 独占模式又是共享模式的锁有哪些&#xff1f; 前言&#xff1a; 资源有两种共享模式&#xff0c;或者说两种同步⽅式&#xff1a; 独占模式&#xff08;Exclusive&am…

类图(类之间的关系)

一.概述 类图(Class diagram)是显示了模型的静态结构&#xff0c;特别是模型中存在的类、类的内部结构以及它们与其他类的关系等。类图不显示暂时性的信息。类图是面向对象建模的主要组成部分。在软件工程中&#xff0c;类图是一种静态的结构图&#xff0c;描述了系统的类的集合…

MySQL调优笔记——慢SQL优化记录(2)

今天调优的原因是&#xff0c;有一个统计报表业务&#xff0c;查询的时间太慢&#xff1b;同时由于数据库的压力是随机性的&#xff0c;这个业务的执行下限和上限相差近20倍&#xff1b;快的时候可以达到600ms&#xff0c;慢的时候有9秒之多&#xff1b; 接下来详细介绍&#x…

SOFA Weekly|SOFARPC 5.10.0 版本发布、SOFA 五周年回顾、Layotto 社区会议回顾与预告...

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展 欢迎留言互动&#xff5e; SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&am…

水电设计院信息管理系统1.0

水电设计公司信息管理系统软件使用说明书 代码太多就不贴了&#xff0c;请在我的资源里下载&#xff0c;已部署在企业进行试运行。https://download.csdn.net/download/weixin_44735475/87704302 目录 1.引言 1 2.项目背景 1 3.系统功能 2 3.1系统功能 2 3.2系统性能 2 3.3系…

精通 TensorFlow 2.x 计算机视觉:第二部分

原文&#xff1a;Mastering Computer Vision with TensorFlow 2.x 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#xff0c;…

【洛谷】P1631 序列合并

【洛谷】 P1631 序列合并 题目描述 有两个长度为 N N N 的单调不降序列 A , B A,B A,B&#xff0c;在 A , B A,B A,B 中各取一个数相加可以得到 N 2 N^2 N2 个和&#xff0c;求这 N 2 N^2 N2 个和中最小的 N N N 个。 输入格式 第一行一个正整数 N N N&#xff1b; 第二…

湫湫系列故事——减肥记Ⅰ

文章目录 湫湫系列故事——减肥记Ⅰ程序设计程序分析湫湫系列故事——减肥记Ⅰ 【问题描述】 对于吃货来说,过年最幸福的事就是吃了,没有之一! 但是对于女生来说,卡路里(热量)是天敌啊! 资深美女湫湫深谙“胖来如山倒,胖去如抽丝”的道理,所以她希望你能帮忙制定一个食…

Omniverse Replicator的“Hello World”

核心功能——Replicator的“Hello World” 学习目标 本教程的目的是介绍基本的 Omniverse Replicator 功能&#xff0c;例如使用一些预定义的 3D 资产创建一个简单的场景&#xff0c;应用随机化&#xff0c;然后将生成的图像写入磁盘以进行进一步处理。 使用复制器 API 要运…

淌入客户市场的“深水区”,锐捷云桌面体验再升级

作者 | 曾响铃 文 | 响铃说 现阶段&#xff0c;云桌面的普惠价值随着行业应用的深化正在不断突显。 以教育为例&#xff0c;教育信息化建设已经跨过了从无到有的阶段&#xff0c;目前正面临着如何降本增效的问题。云桌面的应用&#xff0c;正在有效地解决这个问题。 在响铃…

Java中的null总结

日常工作&#xff0c;遇见几次null的语法报错&#xff0c;整理以下Java中null&#xff1a; &#x1f341; null是一个关键字&#xff0c;对大小写敏感&#xff0c;像public、static… &#x1f341; null是所有引用数据类型的默认值&#xff08;int默认0、boolean默认false…)…

智能面板小程序如何实现跨端开发,并无缝引入ChatGPT?

如何让开发者更便捷高效地开发面板小程序&#xff1f; 全球化 IoT 开发平台服务商涂鸦智能&#xff08;NYSE&#xff1a;TUYA&#xff0c;HKEX&#xff1a;2391&#xff09;原先提供的是一套基于 React Native (简称 RN) 的面板 SDK&#xff0c;但是随着面板规模的不断增长&am…

工程项目管理系统源码+spring cloud 系统管理+java 系统设置+二次开发

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

采购系统是如何管理供应商的?

随着数字化的推进&#xff0c;企业面临着越来越多的供应商管理问题。企业采购数字化转型已经成为大势所趋&#xff0c;对于采购数字化转型而言&#xff0c;供应商管理是重要一环。 供应商准入管理 在供应商准入阶段&#xff0c;企业需要从供应商资质、财务能力、信誉能力、管理…

redis笔记——springboot集成redis

Sprigboot整合 springboot整合数据操作一般会通过官方的一个项目springdata来进行整合&#xff0c;它可以操作很多市面上流行的数据库&#xff0c;并且为java程序提供一套完整的统一的api调用。在springboot2版本之后&#xff0c;原本的jedis被替换成功了lettuce。原因是 jed…

Java读取文件方式

IO流读取 文本内容 按行读取文件内容 指定编码格式&#xff08;推荐&#xff09; public static void main(String[] args) throws UnsupportedEncodingException {read("D:\\test.txt");}public static void read(String path) {BufferedReader reader null;try …

DNS服务器 - 理论

DNS服务器 1. 概念2. DNS域名结构3. 域名的分级4. 域名服务器4.1 层次结构4.2 DNS服务类型 5. 域名解析过程5.1 递归查询与迭代查询5.2 解析流程1. 迭代查询2. 递归查询 6. 高速缓存7. 加上主机缓存后的DNS解析流程8. 常见的域名解析记录9. DNS正向解析和反向解析10. 配置文件介…