2013-07-03 29 views
40

Spring Security 3.1.4.RELEASE以降、古いorg.springframework.security.authentication.encoding.PasswordEncoderhas been deprecatedorg.springframework.security.crypto.password.PasswordEncoderの方が有利です。私のアプリケーションは公開されていないので、非推奨のAPIに移行することにしました。Spring Securityの新しいPasswordEncoderの使用方法

これまで、私はReflectionSaltSourceを持っていました。ユーザーの登録日をパスワードごとに自動的に使用していました。ログイン処理中

String encodedPassword = passwordEncoder.encodePassword(rawPassword, saltSource.getSalt(user)); 

、春にはまた、SHA-1のデフォルトの実装であるため、ユーザーがまたは、私は新しいパスワードエンコーダでこれを達成することはできませんにサインインすることはできませんかどうかを確認適切に私の豆を使用。 - StandardPasswordEncoderには、エンコーダの作成中にグローバルな秘密の塩を追加する機能しかありません。

非推奨のAPIを使用して設定する方法はありますか。

答えて

48

実際に既存のフォーマットでユーザーを登録していない場合は、代わりにBCrypt password encoderに切り替えることをお勧めします。

塩のことをまったく気にする必要がないので、エンコーディングの詳細は完全にカプセル化されています。 BCryptを使用すると、プレーンハッシュアルゴリズムを使用するよりも強く、他の言語を使用するアプリケーションと互換性のある標準でもあります。

新しいアプリケーションのために他のオプションを選択する理由はありません。

+3

実際に登録したユーザーがいる場合はどうなりますか?私はPasswordencoderがある時点で削除されると仮定します。移行する方法は? – Marc

+7

通常、アカウントを移行するには、ユーザーが正常にログインしたときにパスワードを再ハッシュする必要があります。また、移行期間に複数のアルゴリズムをサポートする必要があります。それを超えると、パスワードリセットが必要になるか、最終的には使用されなかった未使用のアカウントをロックまたは削除することができます。あなたのシステムと要件によって異なります。私はあなたが何らかの検索をすると、それに関する議論を見つけることができると確信しています。なぜなら、それは一般的な問題であり、パスワードdbの妥協の数が増えるにつれてより関連性が高くなるからです。少なくともあなたは[plaintext](http://ow.ly/qZQh0)を使用していません:-)。 –

+1

私は生きていて、saltで古いPasswordEncoderを使っているアプリケーションを持っています。新しいPasswordEncoderに移行する方法の例はありますか? – user2213684

3

これを読んで、春のオプションを読んで、ちょうど2回目のルークの答えを読むためにインターネットを回っているので、BCryptを使用してください(春のsource codeに記載されています)。

ハッシュ/塩の理由と、なぜBCryptを使うのかを説明するために私が見つけた最良のリソースは、Salted Password Hashing - Doing it Rightです。

+0

bcryptを使うのは良いアイデアですが、あなたがリンクした記事には、高速ハッシングを使用するなど、多くの恐ろしいアイディアがあります。詳細については、redditのコメントを参照してください。http://www.reddit.com/r/programming/comments/1yrnbo/salted_pa​​ssword_hashing_doing_it_right/cfnaqkl –

17

ここで私のために働いているBCryptの実装です。春のセキュリティClick Here

のより詳細な例については

春-のsecurity.xmlで

<authentication-manager > 
    <authentication-provider ref="authProvider"></authentication-provider> 
    </authentication-manager> 
<beans:bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> 
    <beans:property name="userDetailsService" ref="userDetailsServiceImpl" /> 
    <beans:property name="passwordEncoder" ref="encoder" /> 
</beans:bean> 
<!-- For hashing and salting user passwords --> 
    <beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> 
Javaクラスの

PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 
String hashedPassword = passwordEncoder.encode(yourpassword); 

これが役立つことを願っています。

ありがとうございました

+0

あなたのuserDetailsS​​erviceImplには何が含まれていますか? – Richard

5

私は同様の問題がありました。ユーザーがパスワードを変更したり再登録したくないため、従来の暗号化されたパスワード(Base64/SHA-1/Random salt Encoded)を保持する必要がありました。しかし、私はBCryptエンコーダも使いたいと思っていました。

私の解決策は、方法は、(BCryptedものが$で始まる)のマッチングの前に最初に使用した暗号化参照をチェック別注デコーダを記述することでした。

塩の問題を回避するために、私は変更されたユーザーオブジェクトを介して、salt +暗号化されたパスワードを連結した文字列をデコーダに渡します。

デコーダ

@Component 
public class LegacyEncoder implements PasswordEncoder { 

    private static final String BCRYP_TYPE = "$"; 
    private static final PasswordEncoder BCRYPT = new BCryptPasswordEncoder(); 

    @Override 
    public String encode(CharSequence rawPassword) { 

    return BCRYPT.encode(rawPassword); 
    } 

    @Override 
    public boolean matches(CharSequence rawPassword, String encodedPassword) { 

    if (encodedPassword.startsWith(BCRYP_TYPE)) { 
     return BCRYPT.matches(rawPassword, encodedPassword); 
    } 

    return sha1SaltMatch(rawPassword, encodedPassword); 
    } 

    @SneakyThrows 
    private boolean sha1SaltMatch(CharSequence rawPassword, String encodedPassword) { 

    String[] saltHash = encodedPassword.split(User.SPLIT_CHAR); 

    // Legacy code from old system 
    byte[] b64salt = Base64.getDecoder().decode(saltHash[0].getBytes()); 
    byte[] validHash = Base64.getDecoder().decode(saltHash[1]); 
    byte[] checkHash = Utility.getHash(5, rawPassword.toString(), b64salt); 

    return Arrays.equals(checkHash, validHash); 
    } 

} 

ユーザーオブジェクト

public class User implements UserDetails { 

    public static final String SPLIT_CHAR = ":"; 

    @Id 
    @Column(name = "user_id", nullable = false) 
    private Integer userId; 

    @Column(nullable = false, length = 60) 
    private String password; 

    @Column(nullable = true, length = 32) 
    private String salt; 



@PostLoad 
    private void init() { 

    username = emailAddress; //To comply with UserDetails 
    password = salt == null ? password : salt + SPLIT_CHAR + password; 
    }   

また、新しいbcryptの形式で再エンコードするパスワードにフックを追加し、それを置き換えることができます。したがって、古い方法を段階的に廃止する。