SvelteKit 变更:Cookie 和身份验证
介绍
本文将探讨 SvelteKit 中的 cookie,并学习在 SvelteKitgetSession从 hooks 中移除 cookie 处理程序后,如何使用 cookie 进行身份验证。现在我们只能使用新route system的cookies方法。本文将介绍 SvelteKit 中两种不同的用户身份验证方法。
parent()在路由中使用函数。- 使用 Svelte 商店处理身份验证。
曲奇饼
Cookies 是 SvelteKit 中引入的一种用于处理 cookie 标头的新方法。您可以使用此方法轻松地在 Web 应用程序中处理 cookie。此外,还有一些其他方法,例如 `cookies.get_cookie()`cookies和 `cookies.get_cookie( set) get` delete。
- 设置方法
此方法会设置一个 cookie。这会set-cookie在响应中添加一个标头,同时也会使 cookiecookies.get在当前请求期间可用。
默认情况下启用httpOnly`and`选项,如果您希望客户端 JavaScript 读取 cookie 和/或通过 HTTP 传输 cookie,则必须显式禁用这些选项。`option`选项的默认值为 `true` 。securetruesameSitelax
默认情况下,pathcookie 的路径是当前路径名的“目录”。大多数情况下,您应该显式设置路径path: '/',以使 cookie 在整个应用程序中可用。
设置方法接受三个参数name,value选项options是可选的,所以你可以自行设置。
cookies.set('session', user.entityId, {
path: '/',
httpOnly: true,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 * 30
});
在这里,我使用方法在标头中set设置cookie ,并根据需要定义选项。sessionSet-Cookie
1. name : session (string)
2. value : user.entityId (string)
3. options: {
path: '/',
httpOnly: true,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 * 30
}
- 获取方法
此方法用于获取先前通过cookies.set或从请求标头中设置的 cookie。
Get 方法接受两个参数name,options选项是可选的。
const session = cookies.get('session');
在这里,我使用方法从上面使用方法设置的值中get获取我的session值。cookiesset
- 删除方法
此方法用于删除 cookie,方法是将 cookie 的值设置为空字符串,并将过期日期设置为过去的日期。
删除方法接受两个参数name,options选项是可选的。
await cookies.delete('session');
这就是删除 cookie 所需的全部步骤。
- 序列化方法
它与 set 方法相同,该方法将 cookie 名称-值对序列化为 Set-Cookie 标头字符串。
Sveltekit 中的身份验证流程
在这里,我将解释如何使用 cookie 和 session 来验证用户身份的步骤。
-
所有用户身份验证都始于注册方法之后。因此,首先要确保数据库中已注册用户。
-
创建一个登录路由来处理用户身份验证。在这里,我们将使用 set 方法设置名为“session”的 Cookie。
-
我们将更新我们
hooks.server.ts访问cookies和获取sessioncookie 的方式,使用 get 方法。 -
我们将基于会话获取用户,并向
locals该用户添加数据。 -
接下来
+layout.server.js,我们将访问我们的locals数据并返回用户数据。 -
我们可以使用这些用户数据来设置身份验证的存储,或者按
parent方法使用它。
定义 event.locals 的本地接口,可以在钩子(handle 和 handleError)、仅限服务器的加载函数和 +server.js 文件中访问。
使用 parent() 方法进行身份验证
现在我们将按照流程来编写身份验证流程的代码。
- 创建一个路由来处理登录。它应该包含 `<username>` 和 `<username>`
+page.svelte字段+page.server.js。+page.svelte你需要在其中添加你的login form`<username>`email和 `password<username>` 字段。登录时,它会调用一个 `<username>` 事件处理程序,form action目前+page.server.js这是我们的默认操作。
// +page.server.ts (inside login route)
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad, Actions } from './$types';
import { customResponse } from '$lib/utils';
import { userRepository } from '$lib/Redis/dbRepository';
import * as bcrypt from 'bcrypt';
import { dev } from '$app/environment';
export const actions = {
default: async ({ request, cookies }) => {
const form = await request.formData();
const email = form.get('email');
const password = form.get('password');
if (!email || !password) return customResponse(400, false, 'Email and Password are required');
if (typeof email !== 'string' || typeof password !== 'string')
return customResponse(400, false, 'Enter a valid email and password.');
const user = await userRepository.search().where('email').equals(email).return.first();
const passwordMatch = user && (await bcrypt.compare(password, user.password));
if (!user || !passwordMatch)
return customResponse(400, false, 'You entered the wrong credentials.');
cookies.set('session', user.entityId, {
path: '/',
httpOnly: true,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 * 30
});
// return customResponse(200, true, 'User loggedIn successfully');
throw redirect(307, '/dashboard');
}
};
// customResponse function from lib/utils
import { invalid } from '@sveltejs/kit';
export const customResponse = (status: number, success: boolean, message: string, data?: any) => {
if (success) {
return {
success: success,
message: message,
info: data
};
}
return invalid(status, {
success: success,
message: message,
info: data
});
};
在这里,我正在验证用户,验证成功后,我们使用 set 方法来设置session cookie。
cookies.set('session', user.entityId, {
path: '/',
httpOnly: true,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 * 30
});
- 现在我们将利用我们的技术,
hook.server.ts在需要时向每条路线提供用户数据。
// hook.server.ts
import type { Handle } from '@sveltejs/kit';
import { userRepository } from './lib/Redis/dbRepository';
// custom redirect from joy of code `https://github.com/JoysOfCode/sveltekit-auth-cookies/blob/migration/src/hooks.ts`
function redirect(location: string, body?: string) {
return new Response(body, {
status: 303,
headers: { location }
});
}
const unProtectedRoutes: string[] = [
'/',
'/login',
'/createAdmin',
'/features',
'/docs',
'/deployment'
];
export const handle: Handle = async ({ event, resolve }) => {
const session = event.cookies.get('session');
if (!session && !unProtectedRoutes.includes(event.url.pathname))
return redirect('/login', 'No authenticated user.');
const currentUser = await userRepository.fetch(session as string);
if (currentUser) {
event.locals.user = {
isAuthenticated: true,
name: currentUser.name,
email: currentUser.email,
type: currentUser.user_type,
active: currentUser.active,
phone: currentUser.phone
};
} else {
if (!unProtectedRoutes.includes(event.url.pathname)) return redirect('/', 'Not a valid user');
}
return resolve(event);
};
在这里,我们将使用该方法访问我们的sessioncookie 。getconst session = event.cookies.get('session');
之后我们需要检查sessioncookie 是否存在,并且我们添加了额外的路由检查条件,因为如果用户未登录,我们将进行重定向。
为什么要添加这个额外的路由检查条件?这是因为当用户位于
login某个路由上,而该用户未获得授权时,我们会将其重定向到login一个页面,这将造成无限重定向循环,而我们的浏览器不喜欢这种情况。
验证完成后,我们将从数据库中获取用户并更新本地设置。
event.locals.user = {
isAuthenticated: true,
name: currentUser.name,
email: currentUser.email,
type: currentUser.user_type,
active: currentUser.active,
phone: currentUser.phone
};
- 现在,我们将访问本地服务器
+layout.server.js,并将本地用户数据返回到我们的 Web 应用程序。
// +layout.server.js
export const load = async ({ request, locals, cookies }) => {
return {
user: locals.user
};
};
在这里,我们访问本地数据,然后将其返回到所有页面,因为布局如此,所有数据都可供共享相同布局的每个页面访问。
- 由于
parent方法的存在,在路由中访问数据非常容易。我们将使用路由page.js的load方法来访问数据layout。
// +page.js
export const load = async ({ parent }) => {
const { user } = await parent();
if (user) {
user: user
}
};
这将使路由能够访问您的用户数据。第一次使用时可能会觉得复杂,但操作一次后您就会爱上它。
使用商店进行身份验证
在商店里,我们需要一个auth.js文件才能将商店添加到我们的项目中。
除了这里我们不使用parent()方法之外,其他步骤都与上面相同。我们会创建一个存储,然后访问+layout.server.js数据+layout.js,数据会返回给存储+layout.svelte,最后我们将用户数据设置到存储中。
-
所以请按照所有步骤操作
+layout.server.js,并将用户数据返回到所有页面。 -
然后我们将创建一个商店
lib/auth.js
import { writable } from 'svelte/store';
export const user = writable();
这样就足以满足我们门店的需求了。
- 现在,
+layout.js我们将从文件中访问数据+layout.server.js。
// `+layout.js`
export const load = async function ({ data }) {
return {
user: data.user
};
};
这将把数据返回到我们的+layout.svelte系统中export let data。
// +layout.svelte
<script lang="ts">
import { user } from "$lib/auth";
export let data;
$: $user.set(data.user);
</script>
<slot />
现在我们有了包含用户信息的存储库,并且可以在客户端代码中的任何位置访问它。
这就是我们在 SvelteKit 中使用 cookie 处理身份验证所需的一切。我们还没有讲解如何管理受保护的路由。答案其实已经在本文中有所提及(虽然并不完全准确,但提供了一个处理思路)。你可以稍微思考一下。我可能遗漏了一些内容,或者如果你有任何补充,可以在评论区留言。
资源
最后,我给大家留下一些资源,我写这篇文章时就用到了其中一些。
这是我写给你的。如果你有什么问题或建议,请在评论区留言,也请多多支持❤️。
文章来源:https://dev.to/theether0/sveltekit-changes-session-and-cookies-enb