Loading

[spring security]错误使用spring security内置加密工具BCryptPasswordEncoder引发的性能问题

参考博文

实战代码(十):Springboot RestTemplate连接池
记一次使用BCryptPasswordEncoder,设置了不合理参数导致耗时严重的坑
高安全加密BCrypt及其性能缺陷

背景

项目上线前测试人员对接口进行性能测试时, 发现某个接口TPS仅在27-30左右浮动, CPU占用率接近100%,以下是部分代码

// 通过redis获取当前登录者用户信息
UserInfo u = redisCache.getUserInfo(currentUserId);
// 更新用户信息
u.setProvince(province);
u.setCity(city);
u.setDistrict(district);
u.setPassword(BCryptPasswordEncoder.encode(password));
userMapper.updateById(u);
// 调用第三方接口
HttpUtil.post(url, param);
// 清除用户缓存
 redisCache.clearUserInfo(currentUserId);

分析排查

业务逻辑很简单,由于该接口调用了第三方接口,所以第一反应是围绕这里做优化

上述代码里所用的HttpUtil是hutool工具下的, 查看源码

可以看到每次建立连接时都是断开上次的连接再重新连接, 这里会有一定的NETWORK IO消耗, 先改这里

方案是使用RestTemplate+HttpClient实现连接池, 减少连接的IO消耗

改完后发现TPS依然在27左右, CPU占用率依然接近100%, 随后将调用第三方接口的代码注释掉, 问题依旧.说明问题并不在调用第三方接口 (其实复盘后总结CPU利用率高单NetWorkIO并不高也就可以排除这里)

于是再排查, 注意到每次调用这个接口都要使用Spring Security内置的BCrypt对密码进行加密再存储到数据库, 会不会是这里有性能消耗?

查阅资料后发现确实如此: "BCrypt比传统hash+salt要安全一万倍,但是代价是使用BCrypt做认证对比密码和密文时候,性能也比hash+salt要慢一万倍。"

初步定位到问题点是加密导致的性能损耗!!

解决

设置BCrypt加密时的参数strength, 在保证安全性的前提下提高性能

strength的取值范围是4-31

new BCryptPasswordEncoder(4).encode(passWord);

修改后,TPS提升10倍,维持在270左右, CPU利用率也保持在70%左右

posted @ 2023-02-03 17:20  丘丘CRUD  阅读(658)  评论(0)    收藏  举报