Node-web05-04博客系统登录

登录功能

代码

实现逻辑

  • 创建登录页面 sign_in
  • 创建 posts/sessions API
  • 使用 SignIn Model 校验数据
  • 使用 session 记录登录状态

用 session记录登录状态

  • google 搜索 next.js session
  • 没找到标准答案
  • 搜仓库 发现 example 里有个例子 with-iron-session
  • lib/withSession.tsx
  • 一定不能把密钥写在代码里,测试可以这样,但是生产环境一定不能这样
1
2
3
4
5
6
7
8
9
10
11
12
import {withIronSession} from 'next-iron-session';
import {NextApiHandler} from 'next';

export function withSession(handler: NextApiHandler) {
return withIronSession(handler, {
// password: process.env.SECRET_COOKIE_PASSWORD,
password: 'c2a85490-cc60-4f21-94e8-8dc5dd3220da', //密钥,这个应该用环境变量
cookieName: 'blog',
// 这个选项如果不设置 你本地开发是http的 就会种不下 cookie 获取 user 会是 undefined
cookieOptions: {secure: false}
});
}
  • 然后修改 api/v1/sessions.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import {NextApiHandler} from 'next';
import {SignIn} from '../../../src/model/SignIn';
import {withSession} from "../../../lib/withSession";

const Sessions: NextApiHandler = async (req, res) => {
const {username, password} = req.body;
res.setHeader('Content-Type', 'application/json; charset=utf-8');
const signIn = new SignIn();
signIn.username = username;
signIn.password = password;
await signIn.validate();
if (signIn.hasErrors()) {
res.statusCode = 422;
res.end(JSON.stringify(signIn.errors));
} else {
req.session.set('currentUser', signIn.user);
await req.session.save()
res.statusCode = 200;
res.end(JSON.stringify(signIn.user));
}
};

// 包一层
export default withSession(Sessions);

// 但是遇到了问题 req.session 点不出来,因为没类型,ts无法识别
// 除非我们能对 NextApiRequest 进行一个扩展,添加 session 选项

如何声明对已有类型进行扩展

1
2
3
4
5
6
7
8
9
首先引入 这个类型,然后在这个类上加属性

import * as [原有类型] from '[原有类型]';

declare module '[原有类型]' {
interface MyAddon {
[你的属性]:any
}
}
  • next-env.d.ts 修改如下
1
2
3
4
5
6
7
import * as next from 'next';
declare module 'next' {
import {Session} from 'next-iron-session';
interface NextApiRequest {
session: Session
}
}
  • 然后去登录 http://localhost:3000/sign_in
  • 此时登录成功 会响应一个 set-cookie 头,这个东西对应服务器里的一小块内存。这个session里记录了用户的信息