Spring SecurityのPasswordEncoderクラスを利用すると、ソルト付 + ストレッチングされたハッシュ値を容易に生成して、ログイン機能を簡潔に実装することができます。
しかし、BCryptやPBKDF2、Argon2などのハッシュ関数はそれぞれ決まった性質や形式があってDBのハッシュ値を参照した際に異なったハッシュ値であるとログインが弾かれて失敗してしまいます。
この辺の記事は、ネット上には少ないため、備忘録として記事に残すことにしました。
使用環境
JDK:1.8
Spring Boot:2.1.6.RELEASE
Spring Security:2.1.6.RELEASE
DB:PostgreSQL
Spring Security
毎度お馴染み、WebSecurityConfigurerAdapterを継承するクラスを実装します。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login") // ViewNameとの紐付けが必要
.loginProcessingUrl("/sign_in") // 認証処理が実行される
.usernameParameter("userId") // ログイン時のユーザパラメタ
.passwordParameter("password")
.failureUrl("/login?error")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID") // cookie削除
.invalidateHttpSession(true) // セッション削除
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.headers().addHeaderWriter(headerWriter);
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
ここでログイン機能作成で、その他必要なクラス、htmlファイルについては割愛させていただきます。
そして、テストの為にPostgreSQLの作成したuser_mstテーブルにログインテストを行うためのダミーデータを作成します。
INSERT INTO user_mst (userid, password, torokusha, torokunichiji, koshinsha, koshinnichiji)
VALUES
('id0001', crypt('kokonipassword', gen_salt('bf')), null, CURRENT_TIMESTAMP, null, CURRENT_TIMESTAMP);
これでログイン機能のテストを行うダミーデータの完成です。
ここで注意が必要なのは、ユーザ登録機能を作成する際は、必ずcrypt(‘new password’, gen_salt(‘bf’))を使ってください。
間違っても、crypt(‘new password’, gen_salt(‘md5’));のアルゴリズム形式md5は使用しないように注意してください。
ログインに失敗しますので。
地味に初学者の時にドハマりして3日ぐらい「なんで、なんでログインできないのだ~」となっていたので。
INSERT INTO user_mst (userid, password)
VALUES
('ユーザID', crypt('新しいパスワード', gen_salt('bf')));
この形で問題ないです。
ちなみに検索機能を作成する際のSQL文(SELECT)や更新機能を作成する際のSQL文(UPDATE)についても
同様にcrypt(‘new password’, gen_salt(‘bf’))の型を使ってくださいね。
以上です。