😺
ONSEN GOODS 開発記録 No.9
ユーザー認証機能
実装までの流れ
今回は本格的なデプロイを目指しているアプリなので、JWT(ジョット)を用いてより堅牢なユーザー認証システムを実装していく。
全体的の大まかな流れは、
- データベースの準備(
userテーブルの作成) - 認証用のAPIの追加
- ミドルウェア構築
- ログインページの追加
- APIリクエストへのJWTの付与
といった感じ
データベースを整備
usersテーブルを追加
setup-db.js
await pool.query(`
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
認証用のAPIの追加
認証用のコントローラー(/backend/controllers/authController.js)を作成し、認証用のAPI設定していく。
authController.js
const db = reqire('../db/setup-db');
const bcrypt = reqire('bcrypt');
const jwt = require('jsonwebtoken');
// ユーザー登録
exports.register = async (req, res) => {
const { username, email, password } = req.body;
if (!username || !email || !password) {
return res.status(400).json({ message: 'すべて必須項目です。' });
}
try {
const hash = bcrypt.hashSync(password, 10);
await db.query(`
INSERT INTO users (username, email, password)
VALUES ($1, $2, $3)
`, [username, email, hash]
);
res.status(201).json({ message: 'ユーザー登録完了'});
} catch (error) {
console.error('登録エラー:', error);
}
};
// ログイン
exports.login = async (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ message: 'メールアドレスとパスワードは必須です。' });
}
try {
const result = await db.query('SELECT * FROM users WHERE email = $1',[username]);
if (result.rows.length === 0) {
return res.status(401).josn({ message: 'メールアドレスまたはパスワードが違います'});
}
const user = result.rows[0];
const match = bcrypt.compareSync(password, user.password);
if (!match) {
return res.stutus(401).json({ message: 'メールアドレスまたはパスワードが違います。'});
}
// JWTトークンの生成
const token = jwt.sign({ id: user.id, username: user.username }, process.env.JWT_SECRET, {expiresIn: '2h'});
} catch (error) {
res.status(500).json({ error: 'ログインエラー'});
}
};
JWT認証用ミドルウェアの構築
jwtでの認証を行うミドルウェアを構築する。正直ミドルウェアについての知識はまだまだ浅いがとりあえず書く。
/backend/middleware/auth.js
const jwt = require('jsonwebtoken');
function authenticateJWT(req, res, next) {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: 'トークンがありません。'});
}
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ message: 'トークンが無効です。'});
}
req.user = user;
next();
});
}
module.exports = authenticateJWT;
ログイン・アカウント登録ページの実装
認可、認証に必要なAPIが整備できたので、それに合わせてログインページとアカウント登録ページを実装していく。
もうソースコード上げるのは面倒くさいのでカット
Discussion