Menu
CoddyTech

注册规则

本课属于 Coddy Node.js 学习旅程的“身份验证与安全”单元。第 7 课,共 24 课。

现在,任何人都可以用同一个名字注册两次,或者使用密码 1 注册。注册时必须先检查收到的内容,再存储任何数据。

两个状态码可以说明出了什么问题。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' });
}
challenge icon

挑战

简单

现在,任何人都可以用同一个名字注册两次,也可以使用密码 1 注册。让注册流程在保存任何内容之前先检查收到的信息。

  1. 在 server.js 中,在 POST /signup 的开头清理用户名:删除用户名两端的空格,并将其转换为小写,这样 " Ada " 就会变成 "ada"。如果没有提供用户名,就将其视为空名称。
  2. 仍然在 POST /signup 中:当名称为空,或密码少于 8 个字符时,返回状态码 400 和 {"error": "Pick a username and a password of at least 8 characters"}。密码恰好有 8 个字符时,长度足够。
  3. 如果已经存在使用清理后名称的用户,就返回状态码 409 和 {"error": "That username is taken"}。
  4. 否则,使用小写名称保存用户。201 响应会显示保存的名称:{"username": "ada"},即使请求中使用的是 "Ada"。
  5. 在 POST /login 中,查找用户名之前也用同样的方式清理用户名。这样,ADA 就能登录账号 ada。

试试看:按“运行”。

  • 发送 POST /signup,并传入 {"username": "Ada", "password": "correct horse"}:状态码为 201,响应为 {"username": "ada"}。
  • 发送 POST /signup,并传入 {"username": "ada", "password": "another password"}:状态码为 409,并返回用户名已被占用的错误。
  • 发送 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');
});
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

身份验证与安全中的所有课

自己练习: Express 在线编辑器