「Expressを使ってブログを作成する(パート3):ユーザーシステムの作成」
このシリーズでは、Node.jsのフレームワークであるExpressを使って、シンプルなブログシステムを作成しています。今回は「ユーザーシステムの作成」をテーマに、ユーザー管理機能(サインアップ、ログイン、ログアウト)を実装していきます。このシステムにより、ユーザーが個別のアカウントを作成して、ブログの投稿を管理できるようになります。
1. 環境の準備
まず、前回までのプロジェクトが正しく動作していることを確認してください。今回の実装には、いくつかの新しいパッケージをインストールする必要があります。
bashnpm install express-session passport passport-local bcryptjs
-
express-session: セッションを管理するために使用します。これにより、ユーザーがログインしているかどうかをサーバー側で追跡できます。 -
passport: ユーザー認証を簡単に実装するためのライブラリです。 -
passport-local: ローカル認証(ユーザー名とパスワード)を使用するためのPassport用の戦略です。 -
bcryptjs: ユーザーのパスワードを安全にハッシュ化するために使用します。
これらのパッケージをインストールした後、次のステップに進みます。
2. ユーザーのモデルを作成する
まず、ユーザー情報を保存するためのデータベースモデルを作成します。MongoDBを使用している前提で、Mongooseを利用してユーザーのスキーマを定義します。
bashnpm install mongoose
models/User.jsファイルを作成し、次のように記述します:
javascriptconst mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
userSchema.pre('save', async function(next) {
if (this.isModified('password')) {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
}
next();
});
userSchema.methods.comparePassword = function(candidatePassword) {
return bcrypt.compare(candidatePassword, this.password);
};
const User = mongoose.model('User', userSchema);
module.exports = User;
-
username: ユーザー名(ユニークである必要があり、必須項目として指定) -
password: ユーザーのパスワード(ハッシュ化されて保存される) -
pre('save'): ユーザーが新規作成またはパスワードが変更されるときに、パスワードをハッシュ化します。
3. ユーザー認証の設定
次に、ユーザー認証を実装します。これを行うために、passportを使用します。まず、config/passport.jsファイルを作成し、次のコードを追加します。
javascriptconst passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User');
// ローカルストラテジーの設定
passport.use(new LocalStrategy(
{ usernameField: 'username' },
async (username, password, done) => {
try {
const user = await User.findOne({ username });
if (!user) return done(null, false, { message: 'Incorrect username.' });
const isMatch = await user.comparePassword(password);
if (!isMatch) return done(null, false, { message: 'Incorrect password.' });
return done(null, user);
} catch (err) {
return done(err);
}
}
));
// セッションの保存方法を設定
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id);
done(null, user);
} catch (err) {
done(err);
}
});
-
passport.use: ローカル認証戦略を設定します。ユーザー名とパスワードをチェックし、一致しない場合はエラーメッセージを返します。 -
passport.serializeUserとpassport.deserializeUser: セッションにユーザーIDを保存し、そのIDを使ってユーザー情報を復元します。
4. ルーティングとコントローラの作成
次に、ユーザー関連のルーティングとコントローラを設定します。
4.1 ユーザーのサインアップ
ユーザーが新規アカウントを作成するためのサインアップ機能を実装します。routes/auth.jsファイルを作成し、以下のコードを記述します。
javascriptconst express = require('express');
const passport = require('passport');
const User = require('../models/User');
const router = express.Router();
// サインアップ
router.post('/signup', async (req, res) => {
const { username, password } = req.body;
try {
const user = new User({ username, password });
await user.save();
res.redirect('/login');
} catch (err) {
res.status(500).send('Error creating user.');
}
});
// ログイン
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
}));
// ログアウト
router.get('/logout', (req, res) => {
req.logout();
res.redirect('/');
});
module.exports = router;
-
/signup: 新規ユーザーをデータベースに追加するエンドポイント。 -
/login: ログインエンドポイント。passport.authenticateを使用して、ユーザー認証を行います。 -
/logout: ログアウトして、セッションを破棄します。
5. セッション管理とビューの作成
ユーザーがログインした状態を維持するために、セッションを使います。app.jsの中で、次のように設定します。
javascriptconst express = require('express');
const session = require('express-session');
const passport = require('passport');
const mongoose = require('mongoose');
const User = require('./models/User');
const authRoutes = require('./routes/auth');
const app = express();
// データベース接続
mongoose.connect('mongodb://localhost:27017/blog', { useNewUrlParser: true, useUnifiedTopology: true });
// セッションとPassportの設定
app.use(session({ secret: 'your-secret-key', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
// ルーティングの設定
app.use(authRoutes);
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
ここでは、express-sessionを使ってセッションを設定し、passport.initialize()とpassport.session()を使って認証を処理しています。
6. フロントエンドの作成
最後に、ユーザーがログインしたり、サインアップしたりするためのHTMLフォームを作成します。これを簡単なHTMLテンプレートとして作成し、適切なルーティングを設定して、ユーザーにビューを表示します。
例として、ログインフォームを作成します。
html
<form action="/login" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Loginbutton>
form>
7. 結論
これで、基本的なユーザーシステム(サインアップ、ログイン、ログアウト)が実装されました。これにより、ブログシステムにユーザー管理機能が追加され、ユーザーごとに個別のアカウントを作成し、セッションを管理できるようになりました。次回は、実際の投稿作成機能を追加し、ユーザーごとのデータの操作が可能となるように進めていきます。
