8

認証用のアプリケーションで 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);
}

データベースに塩を文字列で保存します。私の領域では、データベースからデータを取得したいと考えています。これにはトランザクション サービスを使用します。しかし、私のソルトはストロングなので、静的メソッドを使用して 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();    
}

ご協力いただきありがとうございます。

4

4 に答える 4

13

優れた回答https://stackoverflow.com/a/20206115/603901で述べたように、Shiro の DefaultPasswordService は、パスワードごとに一意のソルトを既に生成しています。

ただし、ユーザーごとのソルトにプライベート ソルト (「ペッパー」と呼ばれることもあります) を追加するために、カスタム PasswordService を実装する必要はありません。プライベート ソルトは 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 を使用して作成されました

shiro.ini の構文については、https://github.com/Multifarious/shiro-jdbi-realm/blob/master/src/test/resources/shiro.iniに感謝します。

于 2014-02-12T22:37:44.787 に答える
4

PasswordMatcher / PasswordService を見ましたか?

これには、エンコード/デコード/比較ロジックがすべて組み込まれています。使用するには:

パスワードをデータベースに保存しています:

PasswordService service = new DefaultPasswordService(); // or use injection or shiro.ini to populate this

private User createUserWithHashedPassword(String inName, String inFirstName, String inLastName, String inPassword){

  String hashedPasswordBase64 = service.encryptPassword(inPassword);

  return new User(inName,inFirstName,inLastName,hashedPasswordBase64,strSalt);
}

次に、PasswordMatcher をレルム内のマッチャーとして単純に使用できます。

realm.setCredentialsMatcher(new PasswordMatcher());

または shiro.ini で:

matcher = org.apache.shiro.authc.credential.PasswordMatcher
realm.credentialsMatcher = $matcher
于 2012-09-19T15:59:17.827 に答える
1

塩を節約するためにタイプを変更します。現在、文字列の代わりに byte[] を使用しています。

ByteSource salt  = randomNumberGenerator.nextBytes(32);

byte[] byteTabSalt  = salt.getBytes();

そして、データベースに byteTabSalt をストックします。

于 2012-09-20T13:37:05.400 に答える