1. 为什么我们需要密码加密和会话查询?
在开发后台管理系统或者任何需要用户登录的应用时,有两个问题是我们绕不开的:密码怎么存,以及用户登录后怎么管。我见过不少新手项目,直接把用户的密码用明文存到数据库里,用户登录信息就放在服务器的内存里。这么干,项目小的时候好像没啥问题,一旦用户量上来或者服务器一重启,麻烦就全来了。数据泄露、会话丢失,都是定时炸弹。
SaToken这个框架,我用了好几年了,它最吸引我的地方就是把权限认证这些复杂的事情做得特别简单。今天我们不聊它那些花哨的登录、鉴权功能,就深挖两个非常基础但至关重要的模块:密码加密和会话查询。你可能觉得,加密不就是调个MD5吗?会话查询不就是查一下谁在线吗?但真要在生产环境里用好、用稳,里面的门道可不少。
比如,用户注册时,你怎么处理他的密码?直接MD5一下?现在彩虹表破解MD5太容易了。用AES?密钥怎么管理?再比如,运营人员过来问:“现在有多少用户在线?能不能把那个异常账号踢下线?” 你怎么快速、准确地查出来?这些就是“密码加密”和“会话查询”要解决的实战问题。把它们俩结合起来用,才能真正构筑起应用安全与管理的基石。下面,我就结合自己趟过的坑,带你一步步把它们整合到你的项目里。
2. 实战第一步:为你的密码穿上“盔甲”
密码是用户身份的最后一道防线,绝对不能裸奔。SaToken的sa-token-core模块里自带了一个SaSecureUtil工具类,它把常用的加密方法都封装好了,开箱即用。但用哪个、怎么用,有讲究。
2.1 摘要加密:快速但别用于密码
摘要算法(MD5、SHA1、SHA256)的特点是不可逆,你加密后得不到原文。SaSecureUtil用起来非常简单:
// MD5加密,结果是32位十六进制字符串
String md5 = SaSecureUtil.md5("123456"); // 输出类似:e10adc3949ba59abbe56e057f20f883e
// SHA1加密,结果是40位字符串
String sha1 = SaSecureUtil.sha1("123456");
// SHA256加密,更安全,结果是64位字符串
String sha256 = SaSecureUtil.sha256("123456");
但是,请注意一个重要的误区:千万不要单独用MD5或SHA系列来加密存储用户密码! 因为这些算法速度太快,且相同的密码加密结果永远相同。攻击者可以预先计算好海量密码的哈希值(彩虹表),很容易进行反向破解。它们更适合用于文件完整性校验,或者对一些不敏感的数据生成一个唯一指纹。
那么密码到底怎么存?一个现代的最佳实践是:使用专门为密码设计的、带盐的、慢哈希算法,比如BCrypt。幸运的是,SaToken也考虑到了这一点。
2.2 密码存储的王者:BCrypt加密
BCrypt算法会自动帮我们做三件事:1. 加盐(Salt);2. 多次迭代(工作因子);3. 生成适应未来计算力增长的哈希值。这才是存储密码的正确姿势。
SaToken整合了BCrypt的实现,使用起来同样直观:
import cn.dev33.satoken.secure.BCrypt;
// 对明文密码进行哈希加密
String plainPassword = "mySecretPassword123";
// gensalt() 会自动生成一个盐,默认的log_rounds(工作因子)是10
String hashedPassword = BCrypt.hashpw(plainPassword, BCrypt.gensalt());
System.out.println("加密后的密码:" + hashedPassword);
// 输出示例:$2a$10$N9qo8uLOickgx2ZMRZoMye3Z7MCF6QfAa5u57pG/5PmP8Qbd/CzO
// 如何验证密码?
String candidatePassword = "mySecretPassword123"; // 用户登录时输入的密码
boolean isMatch = BCrypt.checkpw(candidatePassword, hashedPassword);
System.out.println("密码是否匹配:" + isMatch); // 输出:true
关键点解析:
BCrypt.hashpw()的结果是一个固定格式的字符串,里面已经包含了盐值和工作因子。所以你不需要自己单独去存储盐。- 每次调用
BCrypt.gensalt()生成的盐都不同,因此即使两个用户的密码相同,加密后的哈希值也完全不同,彻底杜绝了彩虹表攻击。 BCrypt.checkpw()方法内部会从存储的哈希值中提取盐,然后用相同的算法对候选密码进行计算并比对。
实战建议:在你的用户注册或修改密码服务中,务必使用BCrypt。数据库user表的password字段,存储的就是BCrypt.hashpw()生成的这个字符串。
2.3 对称与非对称加密:保护传输中的秘密
密码存储的问题解决了,那密码在传输中,或者我们系统间传递一些敏感配置信息时呢?这就需要用到可逆的加密算法。
AES对称加密,就像用同一把钥匙锁门和开门。速度快,适合加密大数据。
// 1. 定义密钥(务必妥善保管!)和明文
String secretKey = "ThisI

5285

被折叠的 条评论
为什么被折叠?



