0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

バック:SpringBoot フロント:Next.js メール認証付きユーザー登録機能を実装

Last updated at Posted at 2023-02-18

概要

バックエンド:SpringBoot RestApi
フロントエンド:Next.js TypeScript
でBtoC向けECショップのクローンサイトを作ってます。

今回はログイン機能を実装します。

下の記事の続きですね。
SpringBoot Rest-Apiメール認証付きユーザー登録機能の実装
前回はPostmanを使って挙動を確認しましたが、今回はフロントエンド側でページを作成 API処理を実行してユーザー登録できるようにします。

ユースケース

入力したメールアドレスが本当に所有者なのか確認するため、メールアドレス認証を行います。

1.ユーザーがEmailとPasswordを入力して登録ボタンを押す。
2.システムがデータベースにユーザーを”仮登録”の状態で登録して、認証するためにEmailを送信する。
3.ユーザーが認証メール中のリンクを押すと、登録完了される。

開発環境

OS:windows10

バックエンド側:
IDE:IntelliJ Community
spring-boot-starter-parent 2.75
java : 11

データベース
mysql:8.0.29
クライアントソフト: MySQL Workbench

フロントエンド:
IDE:VScode

├── @types/node@18.11.15
├── @types/react-dom@18.0.9
├── @types/react@18.0.26
├── axios@1.2.1
├── eslint-config-next@13.0.6
├── eslint@8.29.0
├── next-auth@4.18.7
├── next@13.0.6
├── react-bootstrap@2.7.0
├── react-dom@18.2.0
├── react@18.2.0
├── styled-components@5.3.6
├── styled-jsx@5.1.1
└── typescript@4.9.4

実装

作成したファイル一覧

バックエンド
以下リンク参照
SpringBoot Rest-Apiメール認証付きユーザー登録機能の実装

フロントエンド
主に作ったファイルはページ機能があるファイルです。
Next.jsの機能(routing DynamicRouting)を活用しています。
Reactは初回実行時するために、UseEffect使ったぐらいですね。

ファイル名 説明
customerService.ts api処理が入っている ライブラリはaxiosを利用
pages/regsiter.tsx ユーザー情報を入力する時のページ
pages/registerComplete.tsx register.tsxでユーザー登録が成功した時に遷移するページ
pages/verify/[code].tsx メールのリンク先 URLに認証コードの値が入っている。ページを開くと初回実行時、ユーザーを有効化するApiを実行する next.jsのdynamicRouting機能を使ってます。

コード(長いので先に作成したファイル一覧をご覧ください)

customerService.ts

customerService.ts
import axios from 'axios';
import { URLSearchParams } from 'url';
import { Customer } from '../types/customer';
import { response } from 'msw';

export const register= async (inputEmail:string,inputPassword:string) =>{
	return await axios.post(`http://127.0.0.1:5000/api/auth/signup`,
	{
		'email':inputEmail,
		'password':inputPassword
},

)
.then((response)=>{
	return response;
})
.catch((error)=>{
	return error;
})}

export const verify= async (verifyCode:string) =>{
	return await axios.put(`http://127.0.0.1:5000/api/auth/verify`,
	{
		'verifyCode':verifyCode
},
{ headers : {
	'Request-Method' : 'PUT',
	'Content-Type': 'application/json',
	'Access-Control-Allow-Origin': 'http://127.0.0.1:5000/*',
	'Access-Control-Allow-Headers': 'accept, accept-language, content-language, content-type',
	'Access-Control-Allow-Credentials': 'true'
}}
)
.then((response)=>{
	return response;
})
.catch((error)=>{
	return error;
})}






register.tsx

register.tsx
import { useState } from 'react';
import { Customer } from '../types/customer';
import * as customerService from "../service/customerService";
import Router from 'next/router';

// ユーザー登録ページ
// http://127.0.0.1:3000/register
export default function Register() {
	let inputEmail :string;
	let inputPassword :string;
	// ボタンを押したときに実行する関数
	const onRegisterClick = async (event: React.MouseEvent<HTMLButtonElement>) => {
		// todo エラーハンドリングの実装				
		const response = await customerService.register(inputEmail,inputPassword);
		Router.push('/registerComplete')
	}

	// Emailアドレスの入力値を変数に渡す
	const onChangeEmailHandler = (e: React.FormEvent<HTMLInputElement>) => {
		inputEmail=e.currentTarget.value;
	}
	// パスワードの入力値を変数に渡す
	const onChangePasswordHandler = (e: React.FormEvent<HTMLInputElement>) => {
		inputPassword=e.currentTarget.value;
	}
	return(
	<div className="Layout">
			<div>ユーザー登録画面</div>
			入力したEメールに認証メールが送られます。
			<div>Emailアドレス</div>
			<input type="text" onChange={onChangeEmailHandler}></input>		
			<div>パスワード</div>
			<input type="password" onChange={onChangePasswordHandler}></input>
			<br/>
			<br/>
			<button onClick={onRegisterClick} >ユーザー登録</button>
		<style jsx>{`
				.Layout{
					text-align: center;
				}
			`}</style>

	</div>
	) 
  }


registerComplete.tsx

registerComplete.tsx
// ユーザー登録が完了したときに表示するページ
export default function registerComplete(){
return(
	<div>
		仮登録が完了しました。
		認証メールを送りましたので確認お願いします。
	</div>
)

}

verify/[code].tsx

verify/[code].tsx
import { useRouter } from "next/router";
import {useEffect} from 'react';
import * as customerService from "../../service/customerService";

// 認証完了ページ
export default function Verify(){
	// URLのペラメーターverify/〇〇の〇〇部分を変数に渡している
	const {code} = useRouter().query;
	// 初回実行時に実行する
	 useEffect(()=>{
			verify();},[]);
	// 認証コードを送信する関数
	const verify = async()=> {
		const response = await customerService.verify(code as string);
	}

	return (
		<div>
			認証が完了しました。
			認証コード
			<div>{code}</div>
		</div>
	)
}

実装後の検証

gifアニメは左側ブラウザでviewの確認、右側MySQL workbenchでDBを確認しています。

Emailとパスワードを入力して登録ボタンを押すまで

以下情報を入力
捨てメアドサイトで作った適当なアドレスです。
データベースに新しいユーザーが作成されていることを確認できます。
front-register.gif

送られてきたメールのリンクをクリックして認証を完了する

メールのリンクを開くと、仮登録ユーザーのパラメーターが変化し認証が完了します。
enabled=true
virification_code=null

front-completed.gif

課題

例外処理が未実装なので、追加の必要あり
1.バリデーション
2.Eメールアドレスを送信できなかった場合
3.既に認証が完了してるのにリンクを開いた場合
4.ユーザー登録ボタン押したときの待ちが時間が気になった。(本当に動作してるのかわからない)

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?