大丈夫!手順を追えば割と簡単に実装できるよ。
今回は、AWS CLIを使ったDynamoDBのセットアップ、Reactで作成したフロントエンドのログインフォーム、Python Flaskによるバックエンド処理を連携させたユーザー認証システムの構築方法をお伝えします。
- DynamoDBのテーブル作成とデータ登録。
- Reactによるログインフォームとユーザー体験の向上。
- FlaskでのAPI実装とDynamoDB連携。
本ブログで用いているプロジェクトはGitHubリポジトリで公開しています。
以下のリンクからダウンロードしてください。
https://github.com/my-repo-441/dynamodb-login-demo
Contents
システム構成
構成要素
本記事でのReact × Flask × DynamoDBによるログインフォーム実装の構成要素は以下です。
- フロントエンド: React
- バックエンド: Python、Flask
- データベース: AWS DynamoDB
- その他ツール: AWS CLI
構成図
システム構成図と処理の流れは以下です。
- 自身のPC(localhost)上でフロントエンドとバックエンドを起動
- フロントエンドのログインフォームに、メールアドレスとパスワードを入力
- バックエンドからDynamoDBに対して、メールアドレスとパスワードを送信
- DynamoDBから取得したメールアドレスとパスワードと一致するかを確認
- ログインが成功した場合、「ログイン成功」のメッセージ表示後、ホーム画面に遷移。ログイン失敗した場合、「ログイン失敗」のメッセージ表示後、再度ログインフォームに遷移。
デモアプリの実装
以下に、DynamoDBを使ったログイン処理を含むデモアプリの実装手順を記載します。
ソースコード一式はGithubにアップロードしているので、以下の手順を参考にぜひ自身の環境でも動作させてみてください。
本ブログで用いているプロジェクトはGitHubリポジトリで公開しています。
以下のリンクからダウンロードしてください。
https://github.com/my-repo-441/dynamodb-login-demo
前提条件
React × Flask × DynamoDBによるログインフォーム実装を検証するための前提条件は以下です。
- Python:
- バージョン 3.7 以上がインストールされていること。
- 確認方法:
python --version
- Node.js:
- バージョン 14 以上がインストールされていること。
- 確認方法:
node -v
- npm または Yarn:
- npm バージョン 6 以上、または Yarn バージョン 1.22 以上。
- 確認方法:
npm -v
またはyarn -v
- AWS CLI:
- AWS CLIがインストールされており、認証が設定されていること。
- 確認方法:
aws --version
事前準備
アプリを実行するために、githubからソースコードをクローンして、フロントエンドとバックエンドの実行に必要なライブラリ一式をインストールします。
githubからソースコード一式をクローン
以下のコマンドで、githubから本プロジェクトで用いるソースコード一式をクローンします。
git clone https://github.com/my-repo-441/dynamodb-login-demo.git
Pythonの仮想環境の作成
以下のコマンドで、Pythonの仮想環境を作成します。
python -m venv your/venv/directory
source your/venv/directory/bin/activate
Pythonライブラリのインストール
以下のコマンドで、バックエンドの実行に必要なPythonライブラリをインストールします。
cd backend
pip install -r requirements.txt
npmライブラリのインストール
以下のコマンドで、フロントエンドの実行に必要なnpmライブラリをインストールします。
cd frontend
npm install
必要なライブラリをインストールできたよ。
次からは、ようやくDynamoDBのセットアップだね。
DynamoDBのセットアップ
最初に、ユーザーデータを管理するDynamoDBのセットアップを行います。
DynamoDBの役割
DynamoDBはAWSが提供するNoSQLデータベースサービスです。このプロジェクトでは、ユーザーのメールアドレスやパスワードを管理するために使用します。
テーブル作成
以下のPythonコードを使って、DynamoDBテーブル「Users-ReactApp」を作成します。
このテーブルでは、email
をプライマリキー(パーティションキー)として設定します。
- ap-northeast-1:DynamoDBテーブルを作成するリージョンを入力してください。
- Users:任意のテーブル名を入力してください。
import boto3
import time
import traceback
dynamodb = boto3.resource('dynamodb', region_name='ap-northeast-1')
table_name = "Users"
def create_dynamodb_table():
try:
table = dynamodb.create_table(
TableName=table_name,
KeySchema=[
{'AttributeName': 'email', 'KeyType': 'HASH'}
],
AttributeDefinitions=[
{'AttributeName': 'email', 'AttributeType': 'S'}
],
ProvisionedThroughput={
'ReadCapacityUnits': 1,
'WriteCapacityUnits': 1
}
)
print(f"テーブル {table_name} が作成されました。")
table.wait_until_exists()
print("テーブルのステータス:", table.table_status)
except dynamodb.meta.client.exceptions.ResourceInUseException:
print(f"テーブル {table_name} は既に存在します。")
except Exception as e:
print("エラーが発生しました:")
traceback.print_exc()
create_dynamodb_table()
実行例
テーブル Users が作成されました。
テーブルのステータス: CREATING
実行が正常に完了した場合は、DynamoDBコンソール画面からテーブルが作成されていることを確認することができます。
プライマリキーには何を設定してもいいの?
うん。今回はユーザーIDとして一意で、検索に適しているから、emailをプライマリキーにしたけど、ユーザーごとに一意の値であれば何でもいいよ。
サンプルデータの登録
次に、DynamoDBにユーザーデータを登録します。
以下のPythonコードを実行することで、DynamoDBテーブル構成を作成します。
パスワードはハッシュ化して保存し、セキュリティを強化します。
- Table Name: Users
- Primary Key:
email
(文字列) - test@example.com:任意のメールアドレスを入力。
import boto3
from werkzeug.security import generate_password_hash
from datetime import datetime, timezone
import traceback
dynamodb = boto3.resource('dynamodb', region_name='ap-northeast-1')
table_name = "Users"
table = dynamodb.Table(table_name)
def create_user(email, password, **additional_fields):
try:
password_hash = generate_password_hash(password)
created_at = datetime.now(timezone.utc).isoformat()
item = {
'email': email,
'password_hash': password_hash,
'created_at': created_at
}
# 追加のフィールドを動的に登録
item.update(additional_fields)
response = table.put_item(Item=item)
print(f"ユーザー {email} を登録しました。")
return response
except Exception as e:
print("ユーザー登録中にエラーが発生しました:")
traceback.print_exc()
# サンプル登録
create_user('test@example.com', 'securepassword123', role='admin')
実行例
ユーザー test@example.com を登録しました。
テーブルが作成されたら、DynamoDBのコンソール画面 -> 「項目を探索」で確認できます。
Reactでフロントエンド構築
フロントエンドでは、Reactを使用してログインフォームを作成し、ユーザー体験を向上させます。
ログインフォームの作成
以下はReactで作成したログインフォームの例です。
メールアドレスとパスワードを入力できるシンプルなフォームです。
import React, { useState } from "react";
import {
Box,
Button,
FormControl,
FormLabel,
Input,
Heading,
VStack,
useDisclosure,
} from "@chakra-ui/react";
import { useNavigate } from "react-router-dom";
import ResultDialog from "../components/ResultDialog";
function LoginForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [dialogMessage, setDialogMessage] = useState("");
const [isSuccess, setIsSuccess] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
const navigate = useNavigate(); // React Routerのnavigateフック
const handleSubmit = async (e) => {
e.preventDefault();
if (!email || !password) {
setDialogMessage("メールアドレスとパスワードを入力してください。");
setIsSuccess(false);
onOpen();
return;
}
try {
const response = await fetch("http://127.0.0.1:5000/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (response.ok) {
setDialogMessage("ログイン成功!");
setIsSuccess(true);
onOpen();
setTimeout(() => {
onClose();
navigate("/home");
}, 2000);
} else {
setDialogMessage("ログイン失敗。ユーザーIDまたはパスワードを確認してください。");
setIsSuccess(false);
onOpen();
}
} catch (error) {
setDialogMessage("エラーが発生しました。ネットワーク接続を確認してください。");
setIsSuccess(false);
onOpen();
}
};
return (
<Box
w="100%"
maxW="400px"
mx="auto"
mt="50px"
p="6"
boxShadow="lg"
borderRadius="md"
bg="white"
>
<Heading as="h2" size="lg" textAlign="center" mb="6">
ログイン
</Heading>
<form onSubmit={handleSubmit}>
<VStack spacing={4}>
<FormControl id="email" isRequired>
<FormLabel>メールアドレス</FormLabel>
<Input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレスを入力"
/>
</FormControl>
<FormControl id="password" isRequired>
<FormLabel>パスワード</FormLabel>
<Input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="パスワードを入力"
/>
</FormControl>
<Button
type="submit"
colorScheme="blue"
size="lg"
width="full"
mt={4}
>
ログイン
</Button>
</VStack>
</form>
{/* ダイアログ */}
<ResultDialog
isOpen={isOpen}
onClose={onClose}
cancelRef={null}
message={dialogMessage}
isSuccess={isSuccess}
/>
</Box>
);
}
export default LoginForm;
上記により、以下のようなログインフォームが表示されるようになります。
- Chakra UIを活用して見た目を整える。
fetch
を使用してFlaskバックエンドにリクエストを送信。
Flaskでバックエンド構築
バックエンドでは、Flaskを使ってReactからのリクエストを受け取り、DynamoDBと連携します。
処理の概要
以下の部分で、フロントエンドから送信されたリクエスト(メールアドレスとパスワードを取得しています。)
@app.route("/login", methods=["POST"])
def login():
data = request.json
email = data.get("email")
password = data.get("password")
...
以下の部分で、DynamoDBのクエリ処理を行なっています。
具体的には、ユーザー情報を取得して検証する処理。セキュリティ対策として、保存されたパスワードハッシュと入力されたパスワードを比較しています。
user = table.get_item(Key={"email": email}).get("Item")
if user and check_password_hash(user["password_hash"], password):
return jsonify({"message": "ログイン成功!"}), 200
フロントエンドとの通信を可能にするためにFlask-CORSを実装しています。
from flask_cors import CORS
CORS(app)
- DynamoDBからユーザーデータを取得
- パスワードをハッシュ化して保存し、
check_password_hash
で検証。
- パスワードをハッシュ化して保存し、
- レスポンス設計
- 成功時と失敗時で適切なHTTPステータスコードを返す。
フロントエンドとバックエンドの統合
Reactアプリを実行し、Flaskバックエンドと通信できるようにします。
Reactアプリの起動
以下のコマンドでReactアプリを起動します。
npm run dev
出力例
VITE v4.5.5 ready in 130 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h to show help
Flaskサーバーの起動
Flaskバックエンドを起動します。
python app.py
出力例
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 142-848-122
動作確認
以下の手順で動作確認を行います。
- Webアプリにアクセス
- npm run devで起動したhttp://localhost:3000にアクセスします。
- ログインフォームの入力およびバックエンドへの送信
- ReactのログインフォームからユーザーIDとパスワードを入力し、ログインボタンを押下します。
(FlaskサーバーがDynamoDBを参照し、ログイン情報を確認します。)
- ReactのログインフォームからユーザーIDとパスワードを入力し、ログインボタンを押下します。
- ログイン処理の確認
- 「ログイン成功!」のメッセージが表示され、ホーム画面に遷移することを確認します。メールアドレスもしくはパスワードが異なる場合に、ログイン失敗のメッセージ表示されることも確認します。
Webアプリにアクセス
npm run dev
で起動したhttp://localhost:3000
にアクセスします。
ログインフォームの入力およびバックエンドへの送信
DynamoDBテーブル項目に追加したメールアドレスとパスワードを入力します。
ログインフォームで入力するメールアドレスとパスワードは、DynamoDBにテーブル項目を追加した際の以下のコードが該当します。
# サンプル登録
create_user('example.com@gmail.com', 'securepassword123')
ログイン処理の確認
ログインに成功した場合は、以下のような画面遷移が行われます。
↓↓
ホーム画面に遷移
↓↓
DynamoDBに登録したテーブル項目とは異なるメールアドレスとパスワードを入力すると、ログインに失敗します。
ログインに失敗した場合は、メッセージが表示されます。
まとめ
数ステップでFlaskとDynamoDBを使ったユーザー認証が実装できたね。
実際には、CORS対策やJWTによる認証セッションの管理など、他にも実装する必要があるんだけど、ユーザー認証の基本はこれで掴めたかな。
React、Flask、DynamoDBを連携して、ログイン機能を構築する方法を紹介しました。
これを応用すれば、実用的なアプリケーションを簡単に作ることができます。
本プロジェクトのソースコードと手順を参考に、ぜひ試してみてください。
最後まで読んでいただきありがとうございました。
DynamoDBを設定してみたいんだけど、難しい?