注册规则
本课属于 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' });
}挑战
简单现在,任何人都可以用同一个名字注册两次,也可以使用密码 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 响应会显示保存的名称:
{"username": "ada"},即使请求中使用的是"Ada"。 - 在
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');
});
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
身份验证与安全中的所有课
自己练习: Express 在线编辑器