SpringBoot3整合SpringSecurity6添加用户、密码加密的方式
目录
- 写在前面
- 一、密码明文存储的危害
- 二、加密方式及实现
- 2.1 对称加密
- 2.2 非对称加密
- 2.3 哈希加密
- 三、密码加密测试
- 四、添加新用户
- 4.1 替换默认密码加密方式
- 4.2 Controller
- 4.3 Service
- 4.4 测试一下
- 五、小结
写在前面
还记得在之前的文章中,我们在user
表中手动插入了3条数据吗?
当时,大家就会有疑问。这一串密码是怎么来的呢,我们为啥要对密码进行加密?
带着这些疑问,我们继续上路。我们在开发一个应用系统,肯定是少不了用户注册功能的。说到注册,无非就是往user
用户信息表中插入一条数据。
这条数据包含用户名 [xiezhr]、密码 [123456]等字段,而往往 密码这个字段不可能将123456直接存储的,而是通过各种加密手段处理。最终如上图所示,
即使数据库因各种原因泄露,法外狂徒张三也不知道用户的密码,这让系统又加了一把锁。
一、密码明文存储的危害
不知道大家前段时间有没有听到这么一个新闻。爱尔兰数据保护委员会(DPC)对Meta(前Facebook) 处以9100万欧元(7.14亿元人民币)的罚款,
原因正是因为Meta在未加保护或加密的情况下以明文形式存储用户密码。
从Meta事件再次证明了,即使在大的企业,也难免会有所疏漏,虽然事件中并没有提到泄露信息,但一旦泄露,后果真的不可想象。
密码明文存储就像是你把家里的钥匙挂在门上,任何人都可以拿走钥匙,进入你的家;你的日记本没有上锁,任何人都可以打开看;
安全无小事,安全无小事,安全无小事。
二、加密方式及实现
2.1 对称加密
① 简介
就像你和你的好朋友之间有一个只有你们俩知道的秘密暗号。你们用这个暗号来传递信息,别人就算看到了也看不懂。
② 常见算法
- AES(高级加密标准)
- DES(数据加密标准)
②实现
首先,你和你的朋友要商量好一个“暗号”(密钥)。然后,你把想说的话(明文)转换成只有你们俩能懂的暗号(密文)。你的朋友收到后,再用同样的“暗号”把密文变回原话。
2.2 非对称加密
① 简介
你有一个带锁的信箱,你把钥匙分成两把,一把公钥(可以给别人),一把私钥(自己保管)。别人用公钥把信锁上,只有你能用私钥打开
② 常见算法
RSA算法
③ 实现
你生成一对钥匙,公钥和私钥。别人用你的公钥加密信息,然后发给你。你收到后,用自己的私钥解密。
2.3 哈希加密
① 简介
像是把信息扔进一个特殊的搅拌机,出来的是一个固定大小的“信息指纹”。这个“指纹”不能还原成原来的信息。
② 常见算法
MD5
SHA-1
SHA-256
SHA-512
③ 实现
把信息(明文)通过一个哈希函数处理,生成一个哈希值。这个哈希值用来验证信息是否被篡改。
- 选择一个哈希算法(如
SHA-256
)。 - 把明文通过哈希算法处理,生成哈希值。
- 存储或传输哈希值。
- 接收者收到信息后,再次计算哈希值,与收到的哈希值对比,验证信息完整性。
回到Spring Sesurity
中,框架提供了PasswordEncoder
接口来实现密码加密。通过不同的实现,来配置不同Hash
算法(MD5
、SHA-256
、SHA-512
等)
但是仅仅通过上面简单的加密依然不能防止恶意用户的攻击,为什么呢?
恶意用户会预先计算很多密码的加密结果,保存到“表”里。这里的“表”指的就我们常说的彩虹表。
当想要破解某个密码时,就会用这个密码去“表”里查找对应的加密结果,如果找到了,就知道这个密码是什么了。
那么SpringSecurity
怎么才能防止彩虹表攻击呢?
常用的就是使用盐(Salt)
顾名思义,盐就是给密码加点“料”,每次加密时都加点不同的“料”,这样即使两个用户的密码相同,加密后的结果也会因为盐的不同而不同。
Spring Security
可以通过配置密码编码器(如BCryptPasswordEncoder
)来自动为每个密码生成一个唯一的盐来保证安全。
三、密码加密测试
上面说了一堆理论知识,接下来我们来测试下通过BCryptPasswordEncoder
来加密
@Test public void testPasswordEncoder(){ BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); //明文都是xiezhr,但是每次生成的密文是不一致的 String ret1 = encoder.encode("xiezhr"); String ret2 = encoder.encode("xiezhr"); System.out.println("第一次生成密码:"+ret1); System.out.println("第二次生成密码:"+ret2); Assert.isTrue(encoder.matches("xiezhr", ret1), "密码不一致"); Assert.isTrue(encoder.matches("xiezhr", ret2), "密码不一致"); } //输出 第一次生成密码:$2a$10$96WLiLGkHOcxYNw9wWHDeuXYVznW30S7F5u4Stib71gFp3Mq/mENa 第二次生成密码:$2a$10$f1JowhAXqYI1UBF4jRY5AeziL/83NRzWfvUtxoXzgW0xUQ/uLLUWK //这里并没有抛出密码不一致的异常
从上面测试中,我们可以看出,相同明文"xiezhr" 通过BCrypt
算法加密后,每次生成的密文都是不同的。
再通过matches
来验证两次生成的密文,都与“xiezhr” 匹配
四、添加新用户
在前面的学习中,我们知道了怎么进行密码加密,接下来,该轮到实操了。
我们要实现将一个用户添加到数据库中,并且密码进行加密。
4.1 替换默认密码加密方式
在Spring Security
中默认使用的PasswordEncoder
要求数据库中的密码格式为:{id}ppythonassword
。它会根据id去判断密码的加密方式 ,所以我们之前数据库中存储的密码为{bcrypt}$2a$10$GRLdNijsQMUvl/au9ofL.edwmoohzzS7.rmNSJZ.0FxO/BTk76klW
但是我们一般不会采用这种方式。所以就需要替换PasswordEncoder
默认实现方式。我们一般使用SpringSecurity
为我们提供的BCryptPasswordEncoder
。
怎么替换呢?其实非常简单
我们只需要使用把BCryptPasswordEncoder
对象注入http://www.devze.comSpring
容器中,SpringSecurity
就会使用该PasswordEncoder
来进行密码校验。
@Configuration //标明这个类为配置类,spring应用程序一启动,类中的been 就会被初始化在spring容器中 @EnableWebSecurity //开启spring security 自定义配置 public class WebSecurityConfig { @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }
4.2 Controller
添加addUser
方法,用于接收前台传过来的用户信息。这里省略了上一节的代码
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @PostMapping("/addUser") public int addUser(@RequestBody User user){ return userService.addUser(user); } }
4.3 Service
由于要对前台传过来的密码进行加密处理,我们这里需要单独添加addUser
单独处理密码,具体方法如下
1、UserService
public interface UserService extends IService<User> { int addUser(User user); }
2、UserServiceImpl
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired PasswordEncoder passwordEncoder; @Autowired UserMapper userMapper; @Override public int addUser(User user) { String encode = passwordEncoder.encode(user.getPassword()); user.setPassword(encode); user.setEnabled(true); return userMapper.insert(user); } }
4.4 测试一下
到了这里,小伙伴是不是觉得已经大功告成了,我们来用postman工具测试一下
哦豁,报401 Unauthorized
了,这是为啥呢?
我们要对/user/add编程客栈User
进行放行
@Configuration //标明这个类为配置类,spring应用程序一启动,类中的been 就会被初始化在spring容器中 @EnableWebSecurity //开启spring security 自定义配置 public class WebSecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(csrf-> csrf.disable()); http.authorizeHttpRequests(auth -> auth .requestMatchers("/user/addUser").permitAll() .anyRequest().authenticated() ); return http.build(); } }
添加上面代码之后,再用postman测试,用户就正常添加进去了
我们再来看看数据库,Jon这个用户已经加进去了,而且密码123456 也是加过密的
五、小结
到此,我们已经将一个新用户添加到数据库中了,并且用户密码也做了加密处理。
以上操作,我们只是为了演示添加用户的基本操作,实际项目中会比这个复杂一些,不过原理都是一样的。
在实际的前后端分离项目中,我们还会涉及到跨域处理、统一返回结果、再插入用户之前判断用户是否存在等等。
到此这篇关于SpringBoot3整合SpringSecurity6添加用户、密码加密的文章就介php绍到这了,更多相关SpringBoot3整合SpringSecurity6添加用户、密码加密内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论