在我们日常系统中,很多都有用户注册功能,用户注册需要用户名和密码,密码一般我们都采用md5加密的方式,但是用md5加密,对于一个固定的字符串,其md5值是固定的,这样就会出现彩虹表攻击情况。所谓彩虹表攻击就是指攻击者有一张表,里面有密码明文和对应md5值的对应关系,攻击者利用这些关系来破解用户密码。
一般的,md5加密其实也没啥,因为我觉得毕竟彩虹表攻击者少数,只要你的系统还不够大,没人会关注攻击你。树大就容易招风了。
应对这个问题,可以使用BCryptPasswordEncoder加密方式代替MD5加密,BCryptPasswordEncoder每次encode的值都是不一样的,也就是同一个明文,每次加密之后都是不一样的。每次不一样的话,怎么做密码校验呢。BCryptPasswordEncoder提供了match方法,可以对明文和加密后的字符串进行match匹配,匹配上了就返回true,否则返回false。同一个明文,尽管它可以有多个加密串,但是它跟它的加密串一定是match的。
使用BCryptPasswordEncoder也很简单,对于springboot项目,我们只需要建一个自己的类继承一下BCryptPasswordEncoder即可,什么方法都不需要重写。只需要将自己的类注入到spring,或者直接将BCryptPasswordEncoder作为bean注入到spring的配置文件中。非spring项目可以直接new BCryptPasswordEncoder()来创建。
示例代码:
@Component
public class PasswordEncoder extends BCryptPasswordEncoder {
}
@Service
public class UmsMemberServiceImpl implements UmsMemberService {
@Autowired
UmsMemberMapper umsMemberMapper;
@Autowired
PasswordEncoder passwordEncoder;
@Override
public String register(UserMemberDTO userMemberDTO) {
UmsMember t = new UmsMember();
BeanUtils.copyProperties(userMemberDTO, t);
//注册时加密
String encode = passwordEncoder.encode(userMemberDTO.getPassword());
t.setPassword(encode);
int cnt = umsMemberMapper.insert(t);
if(cnt>0){
return "success";
}else{
return "false";
}
}
@Override
public String login(UserMemberDTO userMemberDTO) {
UmsMember um = umsMemberMapper.selectByName(userMemberDTO.getUsername());
if (null == um) return "用户未注册";
//登录时match校验
if (passwordEncoder.matches(userMemberDTO.getPassword(), um.getPassword())) {
return "用户登录成功";
} else {
return "用户名或密码不正确";
}
}
}