分析
密码应该使用为不可逆加密算法,其中MD5是一种简单易使用的算法,主要优点如下:
上面提到了加盐,加盐一般使用给密码后面添加当前时间毫秒数等方法完成,至于为什么需要加盐呢?比如某些网站的用户信息泄露的时候,另外一些非法分子可以进行MD5加密结果暴力破解得出原始密码,并不是他们能够反解密MD5加密结果,而是他们会让很多数据使用MD5算法生成加密结果,然后拿着网站的MD5加密密码去和他们数据库中的数据(彩虹表)进行比对,从而得出我们的原始密码,这种情况是有可能发生的,然后我们可以通过加盐的方式来解决这个问题,加盐可以加固定盐或者随机盐,如果使用固定盐的话,固定盐暴露之后我们的密码依然是不安全的,还可以添加随机盐,比如我们上面提到的在密码后面添加当前时间毫秒数的方法来完成加盐操作,这样的话我们数据库需要存储加密之后的密码和我们的盐(即加在密码的当前时间毫秒数),如果不想这样做,我们可以使用spring提供的加盐机制,接下来我们会提到
做法
对文字进行md5加密
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class Test {
public static void main(String[] args) {
// 1、直接进行md5加密
// 加密:直接进行md5加密,生成32位的16进制加密结果
// 解密:对原生密码直接进行md5加密,然后和数据库中的加密密码对比
String s1 = DigestUtils.md5Hex("123456");
System.out.println(s1);
// 2、加盐之后在进行md5加密
// 加密:加随机盐之后在进行md5加密
// 解密:从数据库中取出盐和加密密码,然后将原文密码+盐之后进行加密,在将加密结果和数据库中的加密密码进行对比
long salt = System.currentTimeMillis();
String s2 = DigestUtils.md5Hex("123456" + salt);
System.out.println(s2);
// 3、使用spring security提供的加密工具对密码进行md5加密(推荐使用)
// 加密:将原文密码直接加密即可,每次之后生成的结果不一样
// 解释:里面加的也有盐,不过是随机盐,但是添加随机盐的算法只有spring官方知道,所以安全性高一点
BCryptPasswordEncoder bpe = new BCryptPasswordEncoder();
String s3 = bpe.encode("123456");
System.out.println(s3);
// 解密:将原文密码和从数据库中取出来的加密密码进行对比,如果返回true,说明两者一样
boolean flag = bpe.matches("123456", s3);
System.out.println(flag);
}
}
结果:
e10adc3949ba59abbe56e057f20f883e
4edaf8c812df9aa68ea048b5fae80b4b
$2a$10$7F8UDbrEhaRiGppllQ2n9O2rB/i/ex2M50wFUE1hexL2iapJFVGuO
true
对文件进行md5加密
import org.apache.commons.codec.digest.DigestUtils;
import java.io.FileInputStream;
public class Test11 {
public static void main(String[] args) throws Exception {
FileInputStream inputStream = new FileInputStream("C:\\download\\百度网盘\\20230223\\html\\1.html");
System.out.println("文件的md5值:" + DigestUtils.md5Hex(inputStream));
}
}
拓展
如果大家不想用框架,我们还可以使用jdk中的包进行md5加密,我这里提供给大家两个工具方法,它们都可以获取md5加密字段,代码如下:
public class MD5Util {
// 获取md5方法1
public static String getMD5One(String source) {
// 判断source是否有效
if (source == null || source.length() == 0) {
// 如果字符串不合法就会抛出异常(其实我认为抛出异常不合法,没必要因为这件事抛出异常)
throw new RuntimeException("字符串" + source + "不合法");
}
// 使用md5加密算法
String algorithm = "md5";
try {
// 获取MessageDigest对象
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
// 获取明文字符串对应的字节数组
byte[] input = source.getBytes();
// 执行加密操作
byte[] output = messageDigest.digest(input);
// 创建BigInteger对象
int signum = 1; // 返回一个正数
BigInteger bigInteger = new BigInteger(signum, output);
// 按照16进制将bigInteger的值转换为字符串
int radix = 16;
String encoded = bigInteger.toString(radix); // 默认小写,改成大写需要追加toUpperCase()方法
return encoded;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错!!!\n" + e);
}
}
// 获取md5方法2
public static String getMD5Two(String source) {
try {
char hexChars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f'};
byte[] bytes = source.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
bytes = md.digest();
int j = bytes.length;
char[] chars = new char[j * 2];
int k = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
chars[k++] = hexChars[b >>> 4 & 0xf];
chars[k++] = hexChars[b & 0xf];
}
return new String(chars);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错!!+" + e);
}
}
}