后端早期使用的是Laravel构建的,用户系统的密码加密方式用的是原生的语法:password_hash
PHP
// $hash = password_hash('broly', PASSWORD_DEFAULT);
$hash = '$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO';
if (password_verify('broly', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
1
2
3
4
5
6
7
8
// $hash = password_hash('broly', PASSWORD_DEFAULT);
$hash='$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO';
if(password_verify('broly',$hash)){
echo'Password is valid!';
}else{
echo'Invalid password.';
}
现在需要部分业务用到Java做用户验证,这里就涉及到密码验证的兼容问题。先来用spring security的BCryptPasswordEncoder测试一下:
Java
package com.dreamlike.dmlkdemo;
import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author Broly
*
*/
public class CryptTests {
@Test
public void bcryptTest() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
System.out.println(bCryptPasswordEncoder.encode("broly"));
// $2a$10$h.cMz2AmkBbkuUKnFY837uCB3/JZgtJUV7BBUnaGWUCrMk/FF4nX.
String encodedPassword = "$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
boolean bMatch = bCryptPasswordEncoder.matches("broly", encodedPassword);
System.out.println(bMatch); // false
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
packagecom.dreamlike.dmlkdemo;
importorg.junit.Test;
importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author Broly
*
*/
publicclassCryptTests{
@Test
publicvoidbcryptTest(){
BCryptPasswordEncoderbCryptPasswordEncoder=newBCryptPasswordEncoder();
System.out.println(bCryptPasswordEncoder.encode("broly"));
// $2a$10$h.cMz2AmkBbkuUKnFY837uCB3/JZgtJUV7BBUnaGWUCrMk/FF4nX.
StringencodedPassword="$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
booleanbMatch=bCryptPasswordEncoder.matches("broly",encodedPassword);
System.out.println(bMatch);// false
}
}
发现测试通不过。网上查了下password_hash()默认的加密算法是CRYPT_BLOWFISH,官方文档有这样一段描述:
CRYPT_BLOWFISH - Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail. Versions of PHP before 5.3.7 only support "$2a$" as the salt prefix: PHP 5.3.7 introduced the new prefixes to fix a security weakness in the Blowfish implementation. Please refer to » this document for full details of the security fix, but to summarise, developers targeting only PHP 5.3.7 and later should use "$2y$" in preference to "$2a$".
可以发现二者之间的区别在于字符串开头 $2a$ 与 $2y$。大意是$2y$开头的是新版本的安全修复。Java仅支持$2a$。
其实解决方法很简单,在判断之前,用正则把$2y$改成$2a$,然后进行判断:
Java
package com.dreamlike.dmlkdemo;
import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author Broly
*
*/
public class CryptTests {
@Test
public void bcryptTest() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
System.out.println(bCryptPasswordEncoder.encode("broly"));
// $2a$10$h.cMz2AmkBbkuUKnFY837uCB3/JZgtJUV7BBUnaGWUCrMk/FF4nX.
// String encodedPassword = "$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
String encodedPassword = "$2a$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
boolean bMatch = bCryptPasswordEncoder.matches("broly", encodedPassword);
System.out.println(bMatch); // true
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
packagecom.dreamlike.dmlkdemo;
importorg.junit.Test;
importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author Broly
*
*/
publicclassCryptTests{
@Test
publicvoidbcryptTest(){
BCryptPasswordEncoderbCryptPasswordEncoder=newBCryptPasswordEncoder();
System.out.println(bCryptPasswordEncoder.encode("broly"));
// $2a$10$h.cMz2AmkBbkuUKnFY837uCB3/JZgtJUV7BBUnaGWUCrMk/FF4nX.
// String encodedPassword = "$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
StringencodedPassword="$2a$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
booleanbMatch=bCryptPasswordEncoder.matches("broly",encodedPassword);
System.out.println(bMatch);// true
}
}
如果本文对您有所帮助,可以请作者喝杯咖啡,感谢支持^_^
支付宝支付
微信支付