md5算法
彩虹表攻击:
简单来说,由于每次md5算法生成的数据都是唯一的,例如:密码:123,对应生成的密文就是abc那么无论什么情况下,利用md5加密后123都与abc相对应,只需要将密码对应生成的密文与密码一一对应,并列出一个表,表中的数据与你的密码相对应,就能找到你设置的密码,这就是彩虹表攻击
/**
* md5 加密算法
* 每次加密后的值都是相同的,不能防御 彩虹表攻击
*/
@Test
public void md5(){
//需要加密的数据
String sourceString ="123456";
String s = DigestUtils.md5DigestAsHex(sourceString.getBytes());
System.out.println("第一次加密"+s);
s = DigestUtils.md5DigestAsHex(sourceString.getBytes());
System.out.println("第二次加密"+s);
}
/* 第一次加密e10adc3949ba59abbe56e057f20f883e
第二次加密e10adc3949ba59abbe56e057f20f883e*/
bcrypt 算法
为了防止出现md5的漏洞,bcrypt加密算法,每一次加密时对应生成的密文都是不相同的,这样就有效的防止了彩虹表的攻击。
/**
*bcrypt算法可以避免彩虹表攻击
*/
@Test
public void bcrypt(){
//需要加密的数据
String sourceString="123456";
BCryptPasswordEncoder bCryptPasswordEncoder =new BCryptPasswordEncoder();
//生成密文
String code =bCryptPasswordEncoder.encode(sourceString);
System.out.println("第一次加密"+code);
boolean matches =bCryptPasswordEncoder.matches(sourceString,code);
System.out.println("第一次验证 = " + matches);
code = bCryptPasswordEncoder.encode(sourceString);
System.out.println("第二次加密"+code);
matches=bCryptPasswordEncoder.matches(sourceString,code);
System.out.println("第二次验证 = " + matches);
}
/* 第一次加密$2a$10$GTjKSntdpVg9zZoZuzz/dOhTnv0A/3ICmD.s97M/F/Ye.RO70aJT6
第一次验证 = true
第二次加密$2a$10$xBBVP/aUp9A0dfkLkETi8.TT7BeWTr2lguAYVe8iwiRMi24Y4DjJq
第二次验证 = true*/
bcrypt 算法应用
应用场景:注册时对密码的加密
在pom文件中导入依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>5.3.2.RELEASE</version>
<scope>test</scope>
</dependency>
在启动类中向spring容器注入PasswordEncoder,保证在项目中只需要生成一次PasswordEncoder对象,可以避免重复生成,所有项目用一个就可以了
//引入bcrypt算法加密数据
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
然后在service中对需要加密的数据进行加密
首先利用@Resource注解注入passwordEncoder
@Resource
private PasswordEncoder passwordEncoder;
其次实现具体逻辑
@Service
public class UmsMemberServiceImpl implements UmsMemberService {
@Resource
private UmsMemberMapper umsMemberMapper;
@Resource
private PasswordEncoder passwordEncoder;
public String register(UmsMemberRegisterParamDTO umsMemberRegisterParamDTO){
UmsMember umsMember = new UmsMember();
//将前端传来的对象转化为数据库存储的对象
BeanUtils.copyProperties(umsMemberRegisterParamDTO,umsMember);
//利用bCrypt算法加密密码
//生成密文
//String encode = passwordEncoder.encode(umsMemberREgisterParamDTO.getPassword());
String encode = passwordEncoder.encode(umsMember.getPassword());
umsMember.setPassword(encode);
umsMemberMapper.insert(umsMember);
return "success";
}
}
在简单登陆中实现运用bcrypt算法
public String login(UmsMemberLoginParamDTO umsMemberLoginParamDTO) {
System.out.println("开始登录!!!!");
UmsMember umsMember = umsMemberMapper.selectByName(umsMemberLoginParamDTO.getUsername());
if(null!=umsMember){
//获得密码
String passwordDb= umsMember.getPassword();
//利用bcrypt算法验证密码
if(!passwordEncoder.matches(umsMemberLoginParamDTO.getPassword(),passwordDb)){
return "密码不正确!!";
}
}else {
return "用户不存在!!";
}
return "token";
}