如何构建自己的身份验证系统
本仓库是YouTube视频的配套内容:https://youtu.be/CcrgG5MjGOk
- 使用passport.js实现Discord OAUTH
passport.use(
new Strategy(
{
clientId: process.env.DISCORD_CLIENT_ID!,
clientSecret: process.env.DISCORD_SECRET_ID!,
callbackUrl: `${process.env.API_URL}/auth/discord/callback`,
scope: ["identify"],
},
async (_accessToken, _refreshToken, profile, done) => {
// 1. 获取id
const discordId = profile._json.id as string;
// 2. 数据库查询
let user = await db.query.users.findFirst({
where: eq(usersTable.discordId, discordId),
});
// 3. 如果用户不存在则创建
if (!user) {
[user] = await db
.insert(usersTable)
.values({
discordId,
})
.returning();
}
// 4. 返回用户
done(null, user);
}
) as any
);
- JWT令牌
const createAuthTokens = (
user: DbUser
): { refreshToken: string; accessToken: string } => {
const refreshToken = jwt.sign(
{ userId: user.id, refreshTokenVersion: user.refreshTokenVersion },
process.env.REFRESH_TOKEN_SECRET!,
{
expiresIn: "30d",
}
);
const accessToken = jwt.sign(
{ userId: user.id },
process.env.ACCESS_TOKEN_SECRET!,
{
expiresIn: "15min",
}
);
return { refreshToken, accessToken };
};
- Cookie设置
// __prod__是一个布尔值,当NODE_ENV为"production"时为true
const cookieOpts = {
httpOnly: true,
secure: __prod__,
sameSite: "lax",
path: "/",
domain: __prod__ ? `.${process.env.DOMAIN}` : "",
maxAge: 1000 * 60 * 60 * 24 * 365 * 10, // 10年
} as const;
export const sendAuthCookies = (res: Response, user: DbUser) => {
const { accessToken, refreshToken } = createAuthTokens(user);
res.cookie("id", accessToken, cookieOpts);
res.cookie("rid", refreshToken, cookieOpts);
};
如何将服务器部署到VPS
如果你还没有VPS,可以选择像Hostinger这样的服务提供商。在结账时使用代码BENAWAD
可获得额外优惠(赞助内容)
- 为了省去麻烦,设置VPS的无密码SSH登录:https://www.hostinger.com/tutorials/how-to-setup-passwordless-ssh/
- 在VPS上安装Dokku:https://dokku.com/docs/getting-started/installation/(我喜欢用它来实现零停机部署)
- Dokku支持的最新Ubuntu版本是22.04(你可以在Hostinger的控制面板中更改版本)
- 创建应用
dokku apps:create api
- 创建数据库 https://dokku.com/docs/deployment/application-deployment/?h=postgresql#create-the-backing-services
- 链接数据库
dokku postgres:link pg api
- 在你的本地计算机上创建Docker镜像
docker build -t example/auth:1 . --platform=linux
- 将Docker镜像发送到VPS
docker image save example/auth:1 | ssh root@123.23.21.31 docker load
- 在VPS中标记镜像
docker tag example/auth:1 dokku/api:latest
- 部署
dokku deploy api latest
- 这一步可能会失败
- 设置环境变量
dokku config:set api FRONTEND_URL=https://example.com ACCESS_TOKEN_SECRET=hj890duj01jd9012j0dj9021390132 REFRESH_TOKEN_SECRET=q90wej9201je091212903291308 DISCORD_SECRET_ID=asdj902j1d0921 DISCORD_CLIENT_ID=129032180312 DOMAIN=example.com
- 这应该会重新部署应用,然后应用应该能正常工作
自定义域名
- 设置DNS,使你的域名指向VPS
- 使用letsencrypt dokku插件在VPS上设置https:https://github.com/dokku/dokku-letsencrypt
- 你需要先设置你的域名:
dokku domains:set api api.example.com
- 你需要先设置你的域名:
VPS安全
https://www.hostinger.com/tutorials/vps-security
前端部署
我喜欢使用Cloudflare pages