天天看点

有一种攻击叫彩虹表攻击

在我们日常系统中,很多都有用户注册功能,用户注册需要用户名和密码,密码一般我们都采用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 "用户名或密码不正确";
        }
    }
}