📝

はじめてのSpringBoot5 ~ログイン機能:カスタマイズ~

2020/12/19に公開

はじめに

はじめまして
私はJavaを研修で少しかじった程度でSpringBootを使用した開発に参加し、てんやわんやしております森田和華です。
全く分からない中から少しずつ調べて実装をしていますが、自分の学習の為にも記事にして残しておこうと思い作成しております。
参考にしていただける際はそのあたりを念頭に置いたうえで参考にしていただければと思います。
もし私の記事を読んでおかしなところなどありましたらご指摘いただけると嬉しいです。
前回までの記事はこちらです。
はじめてのSpringBoot1 ~プロジェクトの作成~
はじめてのSpringBoot2 ~DB接続~
はじめてのSpringBoot3 ~ログイン機能その1~
はじめてのSpringBoot4 ~ログイン機能その2~

環境

SpringBootバージョン:2.4.0
Javaバージョン:8
DB:MySQL 8.0
IDE:eclipse

ログイン画面をカスタマイズする

前回まではデフォルトのログイン画面を利用していましたが実際の業務ではカスタマイズされた画面を使用することの方が多いと思います。
今回はログイン画面のカスタマイズを行っていきたいと思います。

ログイン画面の作成

まず、Usernameとパスワードを入力できる画面を作成します。
今回はカスタマイズ出来ることを検証する程度で考えているので簡単なformとボタンのみとします。

login.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ログイン</title>
</head>
<body>
<p th:if="${ErrorMessage!=null}" th:text="${ErrorMessage}"> <!--ログインエラーの際はエラーメッセージを表示する -->
<p>ログイン</p>
    <form th:action="@{/login}" method="post">
      <div >ユーザー名</div>
        <input type="text" id="username" name="username" placeholder="ユーザ名" required autofocus>
      <div >パスワード</div>
	<input type="password" id="password" name="password" placeholder="パスワード" required>
      <div ><button type="submit">ログイン</button></div>
    </form>
</body>
</html>

ログイン画面のデフォルトを変更する

次はデフォルトログイン画面から作成した画面に変更します。
ここで前回までのWebSecurityConfigでセキュリティに関する設定を追記していきます。

WebSecurityConfig.java
package com.elpmas.test.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
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;

import com.elpmas.test.domain.service.UserDetailsServiceImpl;

/**
 * SpringSecurityを利用するための設定クラス
 * ログイン処理でのパラメータ、画面遷移や認証処理でのデータアクセス先を設定する
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 認可設定を無視するリクエストを設定
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
        		.antMatchers("/resources/**");
    }

    /**
     * 認証・認可の情報を設定する
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            	.antMatchers("/login").permitAll()
                .anyRequest().authenticated();
        http
        	.formLogin()
        		.loginPage("/login") //ログインページとして使用するurlを設定する
        		.usernameParameter("username") //Usernameのパラメータとして使用する項目のnameを設定する
			.passwordParameter("password") //Passwordのパラメータとして使用する項目のnameを設定する
                .defaultSuccessUrl("/sample", true)
                .failureUrl("/eroor") //エラー発生時として使用するurlを設定する
			.permitAll(); //エラー発生画面も未認証でアクセス出来るようにしないといけない。(この記述がないと指定のurlに遷移せずloginにリダイレクトされる)
    }

    /**
     * 認証時に利用するデータソースを定義する設定メソッド
     * ここではDBから取得したユーザ情報をuserDetailsServiceへセットすることで認証時の比較情報としている
     */
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
}

Controllerの作成

MVCパターンをきちんと使用したのは実は初めての私。
Contorollerが何かもう一度調べなおしました。
Contoroller:リクエストをハンドリングしModelとViewの呼び出しを制御するコンポーネント。リクエスト処理の流れを制御する。
ざっくりと解釈するとブラウザ画面(view)から何の処理(Model)を求められているか判別して制御しているというような感じ。

AuthenticationController.java
package com.elpmas.test.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;


@Controller
public class AuthenticationController {

  @GetMapping("/login") //ログイン画面アクセス時はgetでリクエストが飛んでくる(デフォルト時も同様)
    public String getLogin(Model model) {
        return "login";
    }

    @GetMapping("/eroor") //errorが発生した際はエラーメッセージを表示したいので違う処理に入るように制御する
    public String getLoginError(Model model) {
    	model.addAttribute("ErrorMessage","*ユーザー名もしくはパスワードが一致しません");
        return "login";
    }

    //デフォルトではPostでリクエストが発生。カスタマイズ時はユーザーが指定したmethodに従う。
    @PostMapping("/login")
    public String postLogin(Model model) {
        return "sample";
    }
}

動作確認

ソースの準備は以上になります。
では、動作を確認していきましょう。

ログイン画面は無事作成したものに変更されています。

認証成功時

問題なく動きました。

認証失敗時

こちらも無事、エラー発生時の画面が表示されました。

次回

ログイン画面のカスタマイズが出来たのでベースとしてのログイン機能はとりあえず出来たかと思います。
次回以降はこれまでのソースで実はサラッとすすめてしまったけれど、もっと勉強した方がいいところ(DBからのレコードの取得方法、タイムリーフとパラメータ取得など)をすすめていきたいと思います。
ただし私はSpring,Web開発,Java自体(実務では)も初めてで並行して勉強しなければならないので、今後はJavaや画面側の挙動(htmlやJavaScriptなど)の動きも同時にすすめていきます。

参考文献

Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発 (著 株式会社NTTデータ)
https://www.shoeisha.co.jp/book/detail/9784798142470

Discussion