2021年5月12日星期三

记一次使用BCryptPasswordEncoder,设置了不合理参数导致耗时严重的坑

导读

在项目开发中,越来越重视安全相关的功能。在使用Spring Boot进行项目开发的时候,使用Spring Security框架是一个不错的选择。
开发登录认证功能的时候,一般情况都不会将原始密码明文存储到数据库中,那么就需要对密码进行加密,Spring Security推荐使用的是BCryptPasswordEncoder,说明它有可取之处。

问题

问题:在登录认证的时候,每次均需耗费5S以上的时间,这是用户无法忍受的事情。
排查过程:通过visualVM 的线程Dump的信息发现,在自定义的认证过滤器中的attemptAuthentication()方法进入认证之后,在等待验证密码成功返回的时间最长。将目标放在密码比对的方法上,由于注入的是BCryptPasswordEncoder,找到它调用的比对方法matches(),传入原始密码和数据库中的密码,返回是否匹配的布尔值。
既然发现目标了,那就去扣一扣它的源码吧。

BCryptPasswordEncoder.class

/** * Implementation of PasswordEncoder that uses the BCrypt strong hashing function. Clients * can optionally supply a "version" ($2a, $2b, $2y) and a "strength" (a.k.a. log rounds * in BCrypt) and a SecureRandom instance. The larger the strength parameter the more work * will have to be done (exponentially) to hash the passwords. The default value is 10. * * @author Dave Syer */	private Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}");	private final int strength;	private final BCryptVersion version;	private final SecureRandom random;

通过注释,不难发现,生成的密码字符串有一定的规律,构造方法里面可选参数有三个,strength,version,random
参数strength:默认值为10,可选值为4-31;
参数version:默认值为$2a,可选值为$2a, $2b, $2y;
参数random:SecureRandom的实例,默认值为空;

该类中生成密码的方法encode()需要传入原始密码字符串,调用算法实现类BCrypthashpw()方法,增加一个salt参数,该参数的值由BCryptgensalt()结合strength, version, random生成。
进行密码比较,也就是调用matches()方法的时候,首先需要将用户上传的密码(原始密码)进行加密,因此可以得出耗时的操作在于将原始密码加密。

当需要加密的密码相同时,可能影响性能的因素就只有strength, version, random,使用控制变量法来进行测试,但是参数random没有太大测试的意义。
1.改变参数strength的值,保持其余两个值为默认值。

// strength设置为10,也就是默认值时String password = new BCryptPasswordEncoder(10).encode("password");System.out.println(password);

image

// strength设置为16的时候,不要问我为什么测试16,问就是我当时手抽设置的就是16String password = new BCryptPasswordEncoder(16).encode("password");System.out.println(password);

image

// strength设置为20的时候String password = new BCryptPasswordEncoder(20).encode("password");System.out.println(password);

image

由于strength数值越大,耗时越严重,后面的值不测试了(因为测试了25,运行了19分钟都没有出来)。

2.改变参数version的值,保持其余两个值为默认值。

参数version设置为$2a,由于是默认值,故同测试1中的第二个用例。

// versionh设置为$2bString password = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B, 16).encode("password");System.out.println(password);

image

// version设置为$2yString password = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2Y, 16).encode("password");System.out.println(password);

image

总结

通过以上测试可以看出,参数strength的值改变对于生成加密密码的时间影响是最大的。

为甚麽记录这篇随笔?希望对遇到同样问题的你有所帮助。

PS:研究到这里就结束了,保住头发要紧。菜鸟开发第一次写博客,请各位看官轻喷~









原文转载:http://www.shaoqun.com/a/738800.html

跨境电商:https://www.ikjzd.com/

邮乐购物商城:https://www.ikjzd.com/w/1776

拍拍购物:https://www.ikjzd.com/w/2205


导读在项目开发中,越来越重视安全相关的功能。在使用SpringBoot进行项目开发的时候,使用SpringSecurity框架是一个不错的选择。开发登录认证功能的时候,一般情况都不会将原始密码明文存储到数据库中,那么就需要对密码进行加密,SpringSecurity推荐使用的是BCryptPasswordEncoder,说明它有可取之处。问题问题:在登录认证的时候,每次均需耗费5S以上的时间,这是
阿里巴巴 批发:https://www.ikjzd.com/w/1084
asiabill:https://www.ikjzd.com/w/1014
数魔跨境:https://www.ikjzd.com/w/1425.html
淡季亚马逊listing不出单!可以用这招来破局:https://www.ikjzd.com/home/19297
恋爱10年 结婚半年老公就出轨:http://www.30bags.com/a/253264.html
每次爱爱后 老公都逼我写感受:http://lady.shaoqun.com/a/271238.html

没有评论:

发表评论

跨境电商资讯:外贸宣传平台有哪些(出口的

现在很多做外贸的人都非常关注 外贸企业怎么推广 ,而现在推广的途径和平台有很多,企业如果都做,成本和时间精力是一个问题,而且并不是所有的推广渠道都是有用的。今天云程网络就来为大家盘点几个有效的外贸推广渠道。 一、海外社交媒体营销 Facebook,领英等海外社交媒体营销在近几年得...