REDIS集成在Sveltekit:改变游戏管理的游戏管理器
#网络开发人员 #redis #svelte #sveltekit

介绍

众所周知,Sveltekit上个月发布了V1.0,到目前为止,我们都开始在中型项目中使用它。但是Sveltekit中仍然存在一个疼痛点,该痛点正在管理用户auth和Session。但这不会阻止我们使用Sveltekit。因此,我们能做的就是通过自己的魔法最大程度地减少痛苦,从那里我开始制作一个小包装,使痛苦最小化。让我介绍Sveltekit的新会话管理库,该库是@ethercorps/sveltekit-redis-session,它将Redis用作Session Manager。我们都知道Redis的速度有多快,甚至Ben Awad本人都说使用Redis进行会话管理要比其他事情要好得多。我走了那条路,得到了更好的结果,所以我从项目中提取了它并制作了这个包。

资源

先决条件

  • Sveltekit项目
  • redis客户库for nodejs:ioredis
// Install in your project root
pnpm i -D ioredis
  • 安装@ethercorps/sveltekit-redis-session
pnpm i -D @ethercorps/sveltekit-redis-session 

这个用ioredis制成的软件包作为nodejs的主要redis-client,支持异步/等待。

如何使用

我正在使用Typescript,您可以根据您的项目使用JS/TS。

创建和安装所有依赖项后,我们可以从工作开始。

初始化redis会话商店

  • lib目录中创建一个名称sever的文件夹,然后添加一个文件sessionManager.ts7

server目录在lib中具有特殊的含义。 server目录中的任何文件都只能在服务器端逻辑中使用,这将帮助我们不将某些代码导入客户端。

// lib/server/sessionManager.ts

import { RedisSessionStore } from '@ethercorps/sveltekit-redis-session';
import Redis from 'ioredis';
import { SECRET, REDIS_URL } from '$env/static/private';

// Now we will create new Instance for RedisSessionStore
const options = {
  redisClient: new Redis(REDIS_URL)
  secret: SECRET
} 
// These are the required options to use RedisSessionStore.
export const sessionManager = new RedisSessionStore(options)

SECRETREDIS_URL应该是.env文件。
SECRET是不应该被第三方知道的关键。
REDIS_URL看起来像这个redis://username:password@host:port,如果您在系统上正在运行redis,REDIS_URL可能看起来像redis://localhost:6379

  • RedissessionStore的所有可用选项
// option default explanation

1. redisClient > No Default > Required and Accepts a Redis Client from `ioredis`.
2. secret > No Default > Required and Accepts a string which is supposed to be a secret key.
3. cookieName > Default: `session` > Its the name of cookie which will be added to browser. Accepts a string can we anything you want.
4. prefix > Default: `sk-session:` > A prefix for all the keys added to redis which helps to get all active session with the same prefix. Accept a string can we anything and make a unique prefix which does not exist in redis.
5. signed > Default: true > Signed cookies mean that every key that is added in cookie going to be signed to check if its assigned by us. Its accepts boolean value.
6. encrypted > Default: false > If you want to encrypt your cookies using `aes-256-cbc` algorithm with secret key. Which makes it more secure from tempering. It accepts boolean value.
7. useTTL > Default: true > Redis have a functionality to delete a key automatically from redis after a given time.
// Given time always going to be your maxAge of cookie more on it in cookies options.
8. renewSessionBeforeExpire > Default: false > If you want to renew user session and cookie before expiring automatically you can use it. This works with `renewBeforeSeconds`.
9. renewBeforeSeconds > Default: 30 * 60 > This will update session and cookie before 30 min if user active at that time.
It used in combination of `renewSessionBeforeExpire`. It accept number which is supposed to be seconds as default is 30 minutes.
10. serializer > Default: `JSON` > This is used to stringify data and parse back to data which is supposed to be saved in redis. It accepts 
`export type Serializer = {
    stringify: Function;
    parse: Function;
};`

11. cookiesOptions > Default: defaultCookiesOption
const defaultExpireSeconds: number = 60 * 60 * 24; // One day in seconds
const defaultCookiesOption: CookieSerializeOptions = {
    path: '/',
    httpOnly: true,
    sameSite: 'strict',
    secure: !dev,
    maxAge: defaultExpireSeconds
}; > It takes any of the parameter accepted by CookieSerializeOptions type from SvelteKit. These options are for setting cookies for the browser.

> In cookiesOptions we have a field `maxAge` which also our time to live(ttl) for redis key expiration time. maxAge accepts time in seconds and which is also in going to be key expire time in redis. // 

这些都是RedissessionStore接受的所有选项。

// CookieSerializeOptions type of SvelteKit

export interface CookieSerializeOptions {
    domain?: string | undefined;
    encode?(value: string): string;
    expires?: Date | undefined;
    httpOnly?: boolean | undefined;
    maxAge?: number | undefined;
    path?: string | undefined;
    priority?: 'low' | 'medium' | 'high' | undefined;
    sameSite?: true | false | 'lax' | 'strict' | 'none' | undefined;
    secure?: boolean | undefined;
}

// Learn more about cookieSerializationOptions: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/cookie/index.d.ts#L14

redissessionStore 上的所有可用方法

redissessionstore 有多种方法,但其中6种对用户有用,其中5种是主要方法和一种支持方法。

每个方法返回{数据:任何,错误:布尔值,消息:字符串}

redissessionstore 的主要方法:

  1. createNewsession =>接受(cookie,sessiondata,key?='')。它为Redis添加了一个新的会话,并将Cookie设置为Cookie方法,名称为'session'options.cookieName。 cookie是来自requestEvent的cookie,sessiondata是dict cookie,它是用于要保存在redis中的数据,如果您不想设置从crypto.randomuuid函数生成的默认随机键,则键是可选的。它在数据中返回{redis键,没有前缀,cookie value}。

  2. getsession =>仅接受来自requestEvent的cookies。它首先验证基于您的签名或加密方法的cookie。它还检查是否有效更新密钥和cookie到期时间到默认的最大时间,它还检查了续订。它返回您在创建新会话时提供的Redis保存的SessionData。

  3. updatesEssionExpiry =>接受requestEvent的cookies方法。它验证cookie,然后更新到会话和cookie的到期。我们已经根据renewSessionBeforeExpiry选项处理了基本的自动更新,该选项需要在renewBeforeSeconds时间范围内使用活动用户请求。这就是为什么当您想更新cookie时,您可以使用此方法添加自己的逻辑。例如。检查用户活动,最后一个API请求框架等。它返回数据中的cookie值。

  4. delsession =>此还接受了requestEvent的cookies方法。它可以验证cookie如果cookie不有效,它将不会删除会话,而cookie将返回错误:true,您可以在每种方法中处理无效的cookie处理操作。成功验证后,它将返回独特的值,使redis键具有前缀值。

  5. deletecookie =>它还从requestEvent中采用cookie方法。此方法仅在没有任何验证的情况下从浏览器中删除cookie。例如如果您在任何方法中都有验证错误,则可以删除cookie而无需删除REDIS的会话,这只能使用有效的密钥。它返回什么都不会删除,如果有任何错误,它会登机。

其他方法可能对您自己的逻辑有用

  1. _validatecookie =>它从RequestEvent和验证cookie中采用cookie方法,该方法是使用RedissessionStore创建的createNewsession方法。如果没有错误,则返回没有前缀的redis键。

在我们的项目身份验证中使用方法。

在这里,我将展示如何在API(+Server.ts)中使用它们,并且可以在Sveltekit页面操作中使用。我正在做一些假设,例如您已经创建了用户并拥有emailpassword字段,您将处理客户提供的数据验证。

这是我们的SessionManager文件的代码

import { RedisSessionStore } from '@ethercorps/sveltekit-redis-session';
import Redis from 'ioredis';
import { SECRET, REDIS_URL } from '$env/static/private';
export const sessionManger = new RedisSessionStore({
    redisClient: new Redis(REDIS_URL),
    secret: SECRET,
    prefix: 'redisk-example:', // redis key prefix
    cookieName: 'session', // cookie name in browser
    cookiesOptions: {
        maxAge: 10 * 60 // ten minutes
    }
});
  • 第一个示例显示了如何使用createNewsession登录login/+server.ts中的用户
// Github: examples/src/routes/api/login/+server.ts

import { fail, json, redirect } from "@sveltejs/kit";
import type { RequestHandler } from './$types';
import { sessionManger } from '$lib/session';

export const POST = (async ({ request, locals, cookies }) => {

  const { email, password } = await request.json();
  if (
    email !== 'shivam@example.com' ||
    password !== 'Shivam@Meena'
  ) {
    return fail(400, {
      data: { email, password },
      message: 'Invalid credentials'
    });
  } // user validation

/* get user data after validation */
  const { data, error, message } = await sessionManger.createNewSession(cookies, {
    email
  }); // creating new session
  if (error) {
    console.log(message);
    return fail(400, {
      data: { email, password },
      message
    });
  } // error check while creating session
  return json({ success: true, message}); // no error return
}) satisfies RequestHandler;

在上面的示例中,您可以看到我们刚刚通过requestEvent和用户sessiondata将cookie传递给了REDIS创建并添加cookie并添加cookie。

  • 此示例显示了如何在+hooks.server.ts中使用Getession
// Github: examples/src/+hooks.server.ts

import type { Handle } from '@sveltejs/kit';
import { sessionManger } from '$lib/session';
import { redirect } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
    const userSession = await sessionManger.getSession(await event.cookies);
    event.locals = {
        isUserLoggedIn: false,
        user: null
    };
    if (userSession.error) {
        console.log(userSession);
        await sessionManger.deleteCookie(await event.cookies);
        return resolve(event);
    }
    if (userSession && userSession.data) {
        event.locals = {
            isUserLoggedIn: true,
            user: { email: userSession?.data?.email as string }
        };
    }
    return resolve(event);
};

hooks.server.ts中,我们将与我们的cookie进行会话,并且它将返回sessiondata inseressessessessessesseess.data和错误,我将删除cookie。

  • 此示例显示了如何在+logout/server.ts中使用Delsession方法
// Github: examples/src/routes/api/logout/+server.ts

import { json, redirect } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { sessionManger } from '$lib/session';

export const POST = (async ({ request, locals, cookies }) => {
    if (locals && locals.isUserLoggedIn) {
        const { email } = await request.json();
        const deleteData = await sessionManger.delSession(cookies);
        if (deleteData.error) await sessionManger.deleteCookie(cookies);
        return json({ loggedIn: false, message: 'Successfully logged out' });
    }
    throw redirect(302, '/');
}) satisfies RequestHandler;

在这里,我们刚刚通过了我们的cookie并检查了错误,如果发现错误已删除了应用于请求的cookie。

在上面的示例中,您已经看到了我们如何利用createNewSessiongetSessiondelSessiondeleteCookie。您可以在项目中尝试updateSessionExpiry_validateCookie,并在评论中让我知道您的所作所为和逻辑,这将非常有用。


如果有人想建议并贡献,请检查该项目的官方回购。


这是我为你写的。如果您想问或建议任何建议,请发表评论并展示一些爱。