搭建个人知识付费应用系统-(2)用户 Session 管理

本文详细介绍了用户管理的流程,包括FT登录回调、注销、Session管理、Token管理和i18n国际化。重点讲解了如何通过code和refreshToken获取Access Token,以及使用Remix-I18n实现多语言支持。同时,文章提到了用户扩展信息获取的遗留问题,并预告了接下来的主题——DaisyUI主题切换实现。

视频地址: https://www.bilibili.com/video/BV1qG4y1a7Ti/

用户管理

F
T
登录回调
F
T
Start
注销
判断 url 参数
清除 Session 然后 SSO 注销
跳转 SSO 注销链接
Stop
Start
记录 Session
跳回页面
Loader 读取用户信息
是否失效
获取用户信息
Stop
通过 refreshToken 更新 accessToken

Session 管理

SessionStorage

import { createCookieSessionStorage } from '@remix-run/node';

export const sessionStorage = createCookieSessionStorage({
  cookie: {
    name: '_session',
    sameSite: 'lax',
    path: '/',
    httpOnly: true,
    secrets: [process.env.COOKIE_SECRET || 's3cr3t'],
    secure: process.env.NODE_ENV === 'production'
  }
});

export const { getSession, commitSession, destroySession } = sessionStorage;

Token 管理

将 code 换 AccessToken 和 RefreshToken 换 AccessToken 两个方法封装

async function tokenRequest(body) {
  const formBody = [];
  // eslint-disable-next-line
  for (const property in body) {
    const encodedKey = encodeURIComponent(property);
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
    const encodedValue = encodeURIComponent(body[property]);
    formBody.push(`${encodedKey}=${encodedValue}`);
  }
  const res = await fetch(`${process.env.AUTHING_APP_DOMAIN}/oidc/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    },
    body: formBody.join('&')
  });

  const oidcToken = (await res.json()) as OidcResponse;
  return oidcToken;
}

export function code2Token(code: string) {
  const body = {
    client_id: process.env.AUTHING_APP_ID,
    client_secret: process.env.AUTHING_APP_SECRET,
    grant_type: 'authorization_code',
    code
  };

  return tokenRequest(body);
}

export function refreshToken(token: OidcResponse) {
  const body = {
    client_id: process.env.AUTHING_APP_ID,
    client_secret: process.env.AUTHING_APP_SECRET,
    grant_type: 'refresh_token',
    refresh_token: token.refresh_token
  };

  return tokenRequest(body);
}

i18n

插件: https://remix-i18n.js.cool

安装

npm install --save remix-i18n

配置

export interface RemixI18nOptions {
  // 支持的语言
  supportedLanguages: string[];
  // 失败备选
  fallbackLng: string;
}
const i18n = new RemixI18n({
  supportedLanguages: ['en', 'tl', 'da', 'zh'],
  fallbackLng: 'zh'
});

添加语言翻译

i18n.set('locale', {
  hello: '你好'
});

客户端设置

// entry.client.tsx
import { hydrate } from 'react-dom';
import { RemixBrowser } from 'remix';
import { I18nProvider } from 'remix-i18n';
import { i18n, getLocale } from '~/i18n';

const locale = getLocale(window.location.pathname);
i18n.locale(locale);

hydrate(
  <I18nProvider i18n={i18n}>
    <RemixBrowser />
  </I18nProvider>,
  document
);

服务器端设置

// entry.server.tsx
import { renderToString } from 'react-dom/server';
import { RemixServer } from 'remix';
import type { EntryContext } from 'remix';
import { I18nProvider } from 'remix-i18n';
import { i18n, getLocale } from '~/i18n';

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  const locale = getLocale(new URL(request.url).pathname);
  i18n.locale(locale);

  const markup = renderToString(
    <I18nProvider i18n={i18n}>
      <RemixServer context={remixContext} url={request.url} />
    </I18nProvider>
  );

  responseHeaders.set('Content-Type', 'text/html');

  return new Response(`<!DOCTYPE html>${markup}`, {
    status: responseStatusCode,
    headers: responseHeaders
  });
}

语言切换

const i18n = useI18n();
const location = useLocation();
useEffect(() => {
  const locale = getLocale(location.pathname);
  if (locale !== i18n.locale()) {
    i18n.locale(locale);
  }
}, [location]);

使用模板

const { t } = useI18n();

// jsx
<h1>{t('hello')}</h1>;

P.S.

遗留问题: 用户扩展信息的获取(抽空摸索清楚再继续)

下期主题: DaisyUI 主题切换实现

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Willin 老王躺平不摆烂

感谢你这么好看还这么慷慨

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值