Spring Security 3.1.4.RELEASEの時点で、古いorg.springframework.security.authentication.encoding.PasswordEncoder
廃止予定 に代わりorg.springframework.security.crypto.password.PasswordEncoder
が採用されました。私のアプリケーションはまだ一般公開されていないため、廃止されていない新しいAPIに移行することにしました。
これまで、ユーザーの登録日をパスワードのユーザーごとのソルトとして自動的に使用するReflectionSaltSource
がありました。
String encodedPassword = passwordEncoder.encodePassword(rawPassword, saltSource.getSalt(user));
ログインプロセス中に、SpringはBeanを使用して、ユーザーがサインインできるかどうかを適切に検証しました。SHA-1-StandardPasswordEncoder
のデフォルトの実装はエンコーダーの作成中にグローバルシークレットソルトを追加する機能。
非推奨のAPIを使用して設定する合理的な方法はありますか?
実際に既存の形式でユーザーを登録していない場合は、代わりに BCryptパスワードエンコーダー を使用するように切り替えることをお勧めします。
あなたは塩について全く心配する必要がないので、それははるかに少ない面倒です-詳細は完全にエンコーダ内にカプセル化されています。 BCryptの使用は、プレーンハッシュアルゴリズムを使用するよりも強力であり、他の言語を使用するアプリケーションと互換性のある標準でもあります。
新しいアプリケーションに他のオプションを選択する理由は本当にありません。
ここに私のために働いているBCryptの実装があります。
spring-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);
春のセキュリティのより詳細な例 ここをクリック
これが役立つことを願っています。
ありがとう
同様の問題がありました。ユーザーがパスワードを変更したり再登録したくないため、レガシー暗号化パスワード(Base64/SHA-1/Random salt Encoded)を保持する必要がありました。ただし、BCryptエンコーダーも使用したかったのです。
私の解決策は、一致する前に最初に使用された暗号化方式を確認する特注のデコーダーを書くことでした(BCrypted暗号化方式は$
で始まります)。
ソルトの問題を回避するために、変更されたユーザーオブジェクトを介して、ソルト+暗号化されたパスワードの連結Stringをデコーダに渡します。
デコーダー
@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形式でパスワードを再エンコードして置き換えることもできます。したがって、古い方法は廃止されます。
これを読んでSpringのオプションを読んだだけで、ルークの2番目の答えは、BCryptを使用することです(これはSpringの ソースコード で言及されています)。
ハッシュ/塩を使用する理由とBCryptを使用するのが良い選択である理由を説明するために私が見つけた最良のリソースは、ここにあります: ソルトパスワードハッシュ-適切に実行する 。