概要
Spring Securityの認証機能に、パスワードのハッシュ化機能を導入する方法についてまとめた。
前提
以下の記事の続きとなる。
概要 認証エラー時に表示されるエラーメッセージをカスタマイズする方法についてまとめた。 前提 以下の記事の続きとなる。
パスワードのハッシュ化
画面入力値のパスワードをハッシュ化する機能を追加する。
全体像
以下の場所でハッシュ化処理を呼ぶ。
ハッシュ化処理クラス
DaoAuthenticationProvider内のフィールドに定義されたPasswordEncoderインターフェースがハッシュ化処理を担う。
このインターフェースを実装して、用途に応じたパスワード方式を採用する。
パスワードの暗号化クラスは様々あるが、実運用ではBCryptPasswordEncoderを使用することが推奨されている。
このクラスのハッシュ化処理には以下のような特徴がある
・一方向ハッシュ関数であるため、ハッシュ化された値から元のパスワードを復元できない
・入力された平文パスワードと保存されたハッシュ化済みパスワードを安全に照合できる
実装
BCryptPasswordEncoderをBean登録してDaoAuthenticationProviderに設定する。
SecurityConfig.java
package com.example.prototype.biz.security.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService(PasswordEncoder encoder) {
UserDetails disabledUser = User.withUsername("user")
.password(encoder.encode("password"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(disabledUser);
}
@Bean
public DaoAuthenticationProvider authenticationProvider(MessageSource messageSource,
PasswordEncoder passwordEncoder) {
var provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService(passwordEncoder));
provider.setPasswordEncoder(passwordEncoder);
provider.setMessageSource(messageSource);
return provider;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// CSRF機能を無効
.csrf(csrf -> csrf.disable())
// 認可ポリシー定義
.authorizeHttpRequests(auth -> auth
// 認証不要のURL
.requestMatchers(
new AntPathRequestMatcher("/authentication")
).permitAll()
// その他のURLは認証が必要
.anyRequest().authenticated())
// ログイン機能定義
.formLogin(form -> form
.loginPage("/authentication")
.loginProcessingUrl("/authentication/process")
.usernameParameter("loginId")
.passwordParameter("pass")
.defaultSuccessUrl("/", true));
return http.build();
}
}
public PasswordEncoder passwordEncoder() {
PasswordEncoderインターフェースをBean定義する。
PasswordEncoderの実装クラスとして、BCryptPasswordEncoderをDIコンテナに登録する。
照合対象ユーザーを仮取得するUserDetailsServiceを修正して、パスワードを予めハッシュ化しておく。
※”password”をハッシュ化
DaoAuthenticationProviderのPasswordEncoderに、定義したBCryptPasswordEncoderを設定する。
以上でパスワードのハッシュ化機能が認証処理に適用される。
まとめ
☑ 認証機能にパスワードのハッシュ化を導入するには、DaoAuthenticationProviderにPasswordEncoderの実装クラスを設定する
☑ ハッシュ化の実装には、BCryptPasswordEncoderが推奨される
☑ BCryptPasswordEncoderは一方向ハッシュ関数となるため、復号はできない