我在应用程序中使用shiro进行身份验证。我使用带有盐的哈希密码,并将其存储在数据库中,如下所示:
private User createUserWithHashedPassword(String inName, String inFirstName, String inLastName, String inPassword){
ByteSource salt = randomNumberGenerator.nextBytes(32);
byte[] byteTabSalt = salt.getBytes();
String strSalt = byteArrayToHexString(byteTabSalt);
String hashedPasswordBase64 = new Sha256Hash(inPassword, salt, 1024).toBase64();
return new User(inName,inFirstName,inLastName,hashedPasswordBase64,strSalt);
}
我将盐和String一起存储在数据库中。现在在我的领域中,我想从数据库取回数据,为此我使用了事务处理服务。但是我的食盐是强壮的,因此我希望使用静态方法将其转为ByteSource类型:
ByteSource byteSourceSalt = Util.bytes(salt); //where the salt is a String
但是,当我创建我的SaltedAuthenticationInfo时,它不会进行身份验证。
我认为我的问题出在我的convert方法中:
private String byteArrayToHexString(byte[] bArray){
StringBuffer buffer = new StringBuffer();
for(byte b : bArray) {
buffer.append(Integer.toHexString(b));
buffer.append(" ");
}
return buffer.toString().toUpperCase();
}
谢谢你的帮助。
最佳答案
如最佳答案https://stackoverflow.com/a/20206115/603901所述,Shiro的DefaultPasswordService已经为每个密码生成了唯一的盐。
但是,无需实现自定义的PasswordService即可向每个用户的盐添加私有(private)盐(有时称为“胡椒粉”)。可以在shiro.ini中配置专用盐:
[main]
hashService = org.apache.shiro.crypto.hash.DefaultHashService
hashService.hashIterations = 500000
hashService.hashAlgorithmName = SHA-256
hashService.generatePublicSalt = true
# privateSalt needs to be base64-encoded in shiro.ini but not in the Java code
hashService.privateSalt = myVERYSECRETBase64EncodedSalt
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordService.hashService = $hashService
passwordMatcher.passwordService = $passwordService
用于生成匹配的密码哈希的Java代码:
DefaultHashService hashService = new DefaultHashService();
hashService.setHashIterations(HASH_ITERATIONS); // 500000
hashService.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME);
hashService.setPrivateSalt(new SimpleByteSource(PRIVATE_SALT)); // Same salt as in shiro.ini, but NOT base64-encoded.
hashService.setGeneratePublicSalt(true);
DefaultPasswordService passwordService = new DefaultPasswordService();
passwordService.setHashService(hashService);
String encryptedPassword = passwordService.encryptPassword("PasswordForThisUser");
产生的哈希看起来像这样:
$shiro1$SHA-256$500000$An4HRyqMJlZ58utACtyGDQ==$nKbIY9Nd9vC89G4SjdnDfka49mZiesjWgDsO/4Ly4Qs=
专用盐未存储在数据库中,这使得如果对手获得对数据库转储的访问权,则更难破解密码。
本示例是使用shiro-1.2.2创建的
感谢https://github.com/Multifarious/shiro-jdbi-realm/blob/master/src/test/resources/shiro.ini为shiro.ini的语法提供的帮助