加密算法-----BCrypt
一、常见的加密算法:
- 可逆算法:一种可以将加密后的密文还原为原始明文的算法。
- 对称算法:对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。
- 非对称算法:非对称加密是指需要两个密钥来进行加密和解密,这两个秘钥分别是公钥(public key)和私钥(private key),如果用公钥对数据进行加密,只有用对应的私钥才能解密。
- 不可逆算法:一种无法将加密后的密文还原为原始明文的算法。
- 单向散列(hash)加密:是指把任意长的输入串变化成固定长的输出串,并且由输出串难以得到输入串的加密方法。广泛应用于对敏感数据加密,比如用户密码,请求参数,文件加密等。
1.BCrypt(最推荐)
2.Argon2(更安全,但需第三方库)
3. PBKDF2(Java 原生支持,但不如 BCrypt/Argon2)
二、BCrypt的使用
Bcrypt是一种哈希加密算法,被广泛应用于存储密码和进行身份验证。并且Bcrypt算法包含一个重要特性即每次生成的哈希值都不同,这是由于Bcrypt算法在计算时会先生成一个随机的盐值与用户密码一起参与计算最终得到一个加密后的字符串。由于生成的盐值是随机的,所以即使每次使用相同的密码得到结果也是不同的。这样可以有效的防止攻击者使用一些手段破解用户密码。
1.加密工具类
/*** 加密算法工具类*/
public class BCryptUtils {/*** 生成加密后密文** @param password 密码* @return 加密字符串*/public static String encryptPassword(String password) {BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();return passwordEncoder.encode(password);// 加密}
2.判断密码是否相同的逻辑
/*** 判断密码是否相同** @param rawPassword 真实密码* @param encodedPassword 加密后密文* @return 结果*/public static boolean matchesPassword(String rawPassword, String encodedPassword) {BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();return passwordEncoder.matches(rawPassword, encodedPassword);// 密码匹配}
3.Main方法测试
public static void main(String[] args) {System.out.println(encryptPassword("123"));System.out.println(matchesPassword("123", "$2a$10$Nm0bAesQKuPt5CWijLVbmOb5FXxRuoFUbHNwupVp.8DqbYQjf8iUW"));}
输出结果:
封装返回结果
package com.qyy.common.core.domain;import com.qyy.common.core.enums.ResultCode;
import lombok.Getter;
import lombok.Setter;//接口文档
@Getter
@Setter
public class R<T> {private int code; //定义一些固定的code,前后端商量好的 0 1 请求成功 常量 2 3 枚举private String msg; //? 通常是code的辅助说明 一个code 对应一个msgprivate T data; //请求某个接口返回的数据list SysUser 泛型//将封装result的封装方法可以写到R里面
// loginResult.setCode(ResultCode.FAILED_USER_NOT_EXISTS.getCode());
// loginResult.setMsg(ResultCode.FAILED_USER_NOT_EXISTS.getMsg());
// return loginResult;public static <T> R<T> ok() {return assembleResult(null, ResultCode.SUCCESS);}public static <T> R<T> ok(T data) {return assembleResult(data, ResultCode.SUCCESS);}public static <T> R<T> fail() {return assembleResult(null, ResultCode.FAILED);}public static <T> R<T> fail(int code, String msg) {return assembleResult(code, msg, null);}/*** 指定错误码** @param resultCode 指定错误码* @param <T>* @return*/public static <T> R<T> fail(ResultCode resultCode) {return assembleResult(null, resultCode);}private static <T> R<T> assembleResult(T data, ResultCode resultCode) {R<T> r = new R<>();r.setCode(resultCode.getCode());r.setData(data);r.setMsg(resultCode.getMsg());return r;}private static <T> R<T> assembleResult(int code, String msg, T data) {R<T> r = new R<>();r.setCode(code);r.setData(data);r.setMsg(msg);return r;}
}
三、管理员登录-真实加密算法使用
在SysUserServiceImpl类中
修改login方法,借助BCryptUtils.matchesPassword()方法,来判断
用户输入密码是否正确
@Override//维护性、性能、安全public R<String> login(String userAccount, String password) {//通过账号去数据库中查询,对应的用户信息LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();//select password from tb_sys_user where user_account = #{userAccount}SysUser sysUser = sysUserMapper.selectOne(queryWrapper.select(SysUser::getUserId, SysUser::getPassword, SysUser::getNickName).eq(SysUser::getUserAccount, userAccount));return R.fail(ResultCode.FAILED_USER_NOT_EXISTS);}if (BCryptUtils.matchesPassword(password, sysUser.getPassword())) {return R.ok();}return R.fail(ResultCode.FAILED_LOGIN);}
测试成功