登録のルール
CoddyのNode.jsジャーニー「認証とセキュリティ」セクションの一部。レッスン 7/24。
現時点では、誰でも同じ名前で二度登録したり、パスワードに 1 を使って登録したりできます。登録処理では、何かを保存する前に、受け取った内容を確認する必要があります。
問題の内容を示すステータスコードが2つあります。400 Bad Request は、短すぎるパスワードのように、リクエスト自体が受け付けられないことを意味します。409 Conflict は、すでに使われている名前のように、既存のデータと競合することを意味します。
名前の表記も統一する必要があります。Ada と ada は、読む人には同じ人の名前に見えるため、保存する前と検索する前に名前を小文字に変換します。
const email = String(req.body.email ?? '').trim().toLowerCase();
if (await subscribers.findOne({ email })) {
return res.status(409).json({ error: 'Already subscribed' });
}チャレンジ
簡単現状では、誰でも同じ名前で2回登録したり、パスワードに 1 を使ったりできます。何かを保存する前に、受け取った内容を登録処理で確認するようにしましょう。
server.jsのPOST /signupの冒頭で、ユーザー名を整えましょう。前後の空白を取り除いて小文字に変換するので、" Ada "は"ada"になります。ユーザー名が指定されていない場合は、空の名前になります。- 引き続き
POST /signupで、名前が空の場合、またはパスワードが8文字未満の場合は、ステータス400と{"error": "Pick a username and a password of at least 8 characters"}を返します。ちょうど8文字のパスワードは十分な長さです。 - 整えた名前のユーザーがすでに存在する場合は、ステータス409と
{"error": "That username is taken"}を返します。 - それ以外の場合は、小文字にした名前でユーザーを保存します。201レスポンスには、保存した名前が表示されます。リクエストで
"Ada"と指定されていても、{"username": "ada"}になります。 POST /loginでは、ユーザー名を検索する前に同じ方法で整えます。これで、ADAからアカウントadaにログインできます。
試してみましょう:「実行」を押します。
POST /signupに{"username": "Ada", "password": "correct horse"}を送信します。ステータス201と{"username": "ada"}が返されます。POST /signupに{"username": "ada", "password": "another password"}を送信します。ステータス409と「taken」エラーが返されます。POST /loginに{"username": "ADA", "password": "correct horse"}を送信します。ステータス200と{"username": "ada"}が返されます。POST /signupに{"username": "bob", "password": "1234"}を送信します。ステータス400が返されます。POST /signupに{"password": "correct horse"}だけを送信します。この場合もステータス400が返されます。
自分で試してみよう
import express from 'express';
import { users } from './db.js';
import { hashPassword, verifyPassword } from './passwords.js';
const app = express();
app.use(express.json());
app.post('/signup', async (req, res) => {
const { username, password } = req.body;
await users.insertOne({ username, passwordHash: await hashPassword(password) });
res.status(201).json({ username });
});
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = await users.findOne({ username });
if (!user || !(await verifyPassword(password, user.passwordHash))) {
return res.status(401).json({ error: 'Wrong username or password' });
}
res.json({ username: user.username });
});
// signup が保存した内容を表示します。学習用のみです。実際のアプリにこのルートを設けることはありません。
app.get('/debug/users/:username', async (req, res) => {
const user = await users.findOne({ username: req.params.username });
res.json(user ? { username: user.username, passwordHash: user.passwordHash } : null);
});
app.listen(3000, () => {
console.log('Vault is running on port 3000');
});
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
認証とセキュリティのすべてのレッスン
自分で練習してみよう: Expressプレイグラウンド