SSO 我调你老味 02: 你加 token 的样子认真的吗

白白是一名现居上海市的人士。在本文中,她将展示一个先进了一点的登录系统。

前言

相安无事地过了一段时间以后,纯客户端的认证/页面切换最终还是被爆破了。

小白气得学了半个月 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));
  }
}

美塌咧。

以 CC BY-NC-SA 4.0 许可证分发