白白是一名现居上海市的人士。在本文中,她将展示一个先进了一点的登录系统。
前言
相安无事地过了一段时间以后,纯客户端的认证/页面切换最终还是被爆破了。
小白气得学了半个月 shake it。
Middleware!
小白准备从中间隔开用户与服务。于是她非常高兴地写了一个 middleware:
1
2
3
4
5
6
7
8
9
10
11
12
|
// app/middleware.ts
export function middleware(request: NextRequest) {
if (auth.ok()) {
return NextResponse.next();
} else {
return NextResponse.redirect(new URL("/error/401", request.url));
}
}
export const config = {
matcher: "/secret/:path*",
};
|
可是怎么写这个 auth.ok() 呢?每次都要验证一下帐号密码的话自己会被烦死的,于是她想到了
Token!
Token 不赖。
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
|
// app/api/auth/route.ts
import fs from "fs";
function generateAccessToken() {
const alphabet = "0123456789abcdef";
let result = "";
for (let i = 0; i < 32; i++) {
result += alphabet[Math.floor(Math.random() * alphabet.length)];
}
return result;
}
export async function POST(request: NextRequest) {
const { account, password } = await request.json();
if (account === "bai" && password === "super-strong-password") {
let response = NextResponse.json({ status: "ok" });
let accessToken = generateAccessToken();
fs.writeFileSync(
"/not/the/path/to/app/my-secret-file-no-one-can-read.txt",
accessToken
);
response.cookies.set("access-token", accessToken);
return response;
} else {
return NextResponse.json({ status: "not_ok" });
}
}
|
再这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// app/middleware.ts
function authOk(cookieText: string): boolean {
const secret =
fs.readFileSync(
"/not/the/path/to/app/my-secret-file-no-one-can-read.txt"
) || "";
return secret === cookieText;
}
export function middleware(request: NextRequest) {
const cookie = request.cookies.get("access-token") || "invalid";
if (authOk(cookie)) {
return NextResponse.next();
} else {
return NextResponse.redirect(new URL("/error/401", request.url));
}
}
|
美塌咧。