【Spring MVC + Spring Security】認証処理にパスワードハッシュ化機能を導入する方法

概要

Spring Securityの認証機能に、パスワードのハッシュ化機能を導入する方法についてまとめた。

 

前提

以下の記事の続きとなる。

あわせて読みたい

概要 認証エラー時に表示されるエラーメッセージをカスタマイズする方法についてまとめた。   前提 以下の記事の続きとなる。

 

パスワードのハッシュ化

画面入力値のパスワードをハッシュ化する機能を追加する。

 

全体像

以下の場所でハッシュ化処理を呼ぶ。

 

▲DaoAuthenticationProviderからパスワードハッシュ化処理を委譲する

 

ハッシュ化処理クラス

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();
    }
}


 

@Bean
public PasswordEncoder passwordEncoder() {

PasswordEncoderインターフェースをBean定義する。

 

return new BCryptPasswordEncoder();

PasswordEncoderの実装クラスとして、BCryptPasswordEncoderをDIコンテナに登録する。

 

.password(encoder.encode(“password”))

照合対象ユーザーを仮取得するUserDetailsServiceを修正して、パスワードを予めハッシュ化しておく。
※”password”をハッシュ化

 

provider.setPasswordEncoder(passwordEncoder);

DaoAuthenticationProviderのPasswordEncoderに、定義したBCryptPasswordEncoderを設定する。

以上でパスワードのハッシュ化機能が認証処理に適用される。

 

まとめ

 

☑ 認証機能にパスワードのハッシュ化を導入するには、DaoAuthenticationProviderにPasswordEncoderの実装クラスを設定する

☑ ハッシュ化の実装には、BCryptPasswordEncoderが推奨される

☑ BCryptPasswordEncoderは一方向ハッシュ関数となるため、復号はできない

 

スポンサーリンク