Advanced

Sessions

编辑此页面

当需要用户信息时,通常检查请求中的信息来完成。客户端和服务器执行此操作的最佳方式是使用 cookies。

Request 对象可用于访问 Cookie 标头,然后可以解析这些标头以获取特定 cookie 的值。例如,"session" 可用于识别会话。幸运的是,Nitro 已经内置了支持这一功能的辅助函数。

例如,如果你想使用 cookie 来识别用户,你可以使用来自 vinxi/httpuseSession 辅助函数:

/lib/session.ts
import { useSession } from "vinxi/http";
export async function getUser(request: Request) {
const session = await useSession({
password: process.env.SESSION_SECRET
});
}

会话 cookie 可用于获取有关请求的会话数据。但是,会话数据的存储和检索方式取决于useSession 的实现。

通常,userId 将保存在会话数据中,如果找不到,则表示请求未经过身份验证。当找不到用户时,getUser 函数会返回一个 null,如果找到用户,它将用于从数据库中获取用户:

/lib/session.ts
import { useSession } from "vinxi/http";
export async function getUser(): Promise<User | null> {
const session = await useSession({
password: process.env.SESSION_SECRET
});
const userId = session.data.userId;
if (!userId) return null;
return await store.getUser(userId);
}

这个辅助工具可以在任何需要验证请求的地方使用,包括服务器函数和 API 路由

此外,您可以将其与从 solid-router 提供的 cache一起使用,以确保只有经过身份验证的用户才能访问数据。这样,如果用户未经过身份验证,请求将被重定向到登录页面。

/routes/api/store/admin.ts
import { query, createAsync, redirect } from "@solidjs/router";
const getUsers = query(async (id: string) => {
"use server";
const user = await getUser();
if (!user) throw redirect("/login");
return store.getUsers(id, "*");
}, "users");
// page component
export default function Users() {
const users = createAsync(() => getUsers());
}

这也允许以类似的方式登录和退出会话:

/routes/session.server.ts
import { redirect } from "@solidjs/router";
import { useSession } from "vinxi/http";
type UserSession = {
userId?: number;
};
function getSession() {
return useSession({
password: process.env.SESSION_SECRET
});
}
export async function login(formData: FormData) {
const username = String(formData.get("username"));
const password = String(formData.get("password"));
// do validation
try {
const session = await getSession();
const user = await db.user.findUnique({ where: { username } });
if (!user || password !== user.password) return new Error("Invalid login");
await session.update((d: UserSession) => (d.userId = user!.id));
} catch (err) {
return err as Error;
}
throw redirect("/");
}
export async function logout() {
const session = await getSession();
await session.update((d: UserSession) => (d.userId = undefined));
throw redirect("/login");
}
报告此页面问题