perf: token

This commit is contained in:
archer
2023-08-05 11:32:43 +08:00
parent eb5a252654
commit 761ae74b0a
13 changed files with 69 additions and 45 deletions

View File

@@ -3,6 +3,7 @@ import { getErrText } from '@/utils/tools';
import { parseStreamChunk, SSEParseData } from '@/utils/sse'; import { parseStreamChunk, SSEParseData } from '@/utils/sse';
import type { ChatHistoryItemResType } from '@/types/chat'; import type { ChatHistoryItemResType } from '@/types/chat';
import { StartChatFnProps } from '@/components/ChatBox'; import { StartChatFnProps } from '@/components/ChatBox';
import { getToken } from '@/utils/user';
interface StreamFetchProps { interface StreamFetchProps {
url?: string; url?: string;
@@ -24,7 +25,8 @@ export const streamFetch = ({
const response = await window.fetch(url, { const response = await window.fetch(url, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json',
token: getToken()
}, },
signal: abortSignal.signal, signal: abortSignal.signal,
body: JSON.stringify({ body: JSON.stringify({

View File

@@ -1,5 +1,5 @@
import axios, { Method, InternalAxiosRequestConfig, AxiosResponse } from 'axios'; import axios, { Method, InternalAxiosRequestConfig, AxiosResponse } from 'axios';
import { clearCookie } from '@/utils/user'; import { clearToken, getToken } from '@/utils/user';
import { TOKEN_ERROR_CODE } from '@/service/errorCode'; import { TOKEN_ERROR_CODE } from '@/service/errorCode';
interface ConfigType { interface ConfigType {
@@ -18,7 +18,7 @@ interface ResponseDataType {
*/ */
function requestStart(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig { function requestStart(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
if (config.headers) { if (config.headers) {
// config.headers.Authorization = getToken(); config.headers.token = getToken();
} }
return config; return config;
@@ -57,7 +57,7 @@ function responseError(err: any) {
} }
// 有报错响应 // 有报错响应
if (err?.code in TOKEN_ERROR_CODE) { if (err?.code in TOKEN_ERROR_CODE) {
clearCookie(); clearToken();
window.location.replace( window.location.replace(
`/login?lastRoute=${encodeURIComponent(location.pathname + location.search)}` `/login?lastRoute=${encodeURIComponent(location.pathname + location.search)}`
); );

View File

@@ -2,6 +2,7 @@ import type { UserType } from '@/types/user';
import type { PromotionRecordSchema } from '@/types/mongoSchema'; import type { PromotionRecordSchema } from '@/types/mongoSchema';
export interface ResLogin { export interface ResLogin {
user: UserType; user: UserType;
token: string;
} }
export interface PromotionRecordType { export interface PromotionRecordType {

View File

@@ -3,7 +3,7 @@ import { Box, Flex, useTheme } from '@chakra-ui/react';
import { useGlobalStore } from '@/store/global'; import { useGlobalStore } from '@/store/global';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { clearCookie } from '@/utils/user'; import { clearToken } from '@/utils/user';
import { useUserStore } from '@/store/user'; import { useUserStore } from '@/store/user';
import { useConfirm } from '@/hooks/useConfirm'; import { useConfirm } from '@/hooks/useConfirm';
import PageContainer from '@/components/PageContainer'; import PageContainer from '@/components/PageContainer';
@@ -77,7 +77,7 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
(tab: string) => { (tab: string) => {
if (tab === TabEnum.loginout) { if (tab === TabEnum.loginout) {
openConfirm(() => { openConfirm(() => {
clearCookie(); clearToken();
setUserInfo(null); setUserInfo(null);
router.replace('/login'); router.replace('/login');
})(); })();

View File

@@ -3,7 +3,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response'; import { jsonRes } from '@/service/response';
import { connectToDatabase } from '@/service/mongo'; import { connectToDatabase } from '@/service/mongo';
import { User } from '@/service/models/user'; import { User } from '@/service/models/user';
import { setCookie } from '@/service/utils/tools'; import { generateToken, setCookie } from '@/service/utils/tools';
export default async function handler(req: NextApiRequest, res: NextApiResponse) { export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try { try {
@@ -32,11 +32,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
throw new Error('密码错误'); throw new Error('密码错误');
} }
setCookie(res, user._id); const token = generateToken(user._id);
setCookie(res, token);
jsonRes(res, { jsonRes(res, {
data: { data: {
user user,
token
} }
}); });
} catch (err) { } catch (err) {

View File

@@ -4,7 +4,7 @@ import { jsonRes } from '@/service/response';
import { User } from '@/service/models/user'; import { User } from '@/service/models/user';
import { AuthCode } from '@/service/models/authCode'; import { AuthCode } from '@/service/models/authCode';
import { connectToDatabase } from '@/service/mongo'; import { connectToDatabase } from '@/service/mongo';
import { setCookie } from '@/service/utils/tools'; import { generateToken, setCookie } from '@/service/utils/tools';
import { UserAuthTypeEnum } from '@/constants/common'; import { UserAuthTypeEnum } from '@/constants/common';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) { export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
@@ -56,11 +56,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
username username
}); });
setCookie(res, user._id); const token = generateToken(user._id);
setCookie(res, token);
jsonRes(res, { jsonRes(res, {
data: { data: {
user user,
token
} }
}); });
} catch (err) { } catch (err) {

View File

@@ -5,7 +5,7 @@ import { User } from '@/service/models/user';
import { AuthCode } from '@/service/models/authCode'; import { AuthCode } from '@/service/models/authCode';
import { connectToDatabase } from '@/service/mongo'; import { connectToDatabase } from '@/service/mongo';
import { UserAuthTypeEnum } from '@/constants/common'; import { UserAuthTypeEnum } from '@/constants/common';
import { setCookie } from '@/service/utils/tools'; import { generateToken, setCookie } from '@/service/utils/tools';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) { export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try { try {
@@ -48,11 +48,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
throw new Error('获取用户信息异常'); throw new Error('获取用户信息异常');
} }
setCookie(res, user._id); const token = generateToken(user._id);
setCookie(res, token);
jsonRes(res, { jsonRes(res, {
data: { data: {
user user,
token
} }
}); });
} catch (err) { } catch (err) {

View File

@@ -2,10 +2,7 @@
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response'; import { jsonRes } from '@/service/response';
import { User } from '@/service/models/user'; import { User } from '@/service/models/user';
import { AuthCode } from '@/service/models/authCode';
import { connectToDatabase } from '@/service/mongo'; import { connectToDatabase } from '@/service/mongo';
import { UserAuthTypeEnum } from '@/constants/common';
import { setCookie } from '@/service/utils/tools';
import { authUser } from '@/service/utils/auth'; import { authUser } from '@/service/utils/auth';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) { export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {

View File

@@ -1,4 +1,4 @@
import React, { useState, useCallback, useEffect } from 'react'; import React, { useState, useCallback } from 'react';
import styles from './index.module.scss'; import styles from './index.module.scss';
import { Box, Flex, Image } from '@chakra-ui/react'; import { Box, Flex, Image } from '@chakra-ui/react';
import { PageTypeEnum } from '@/constants/user'; import { PageTypeEnum } from '@/constants/user';
@@ -10,6 +10,7 @@ import { useChatStore } from '@/store/chat';
import LoginForm from './components/LoginForm'; import LoginForm from './components/LoginForm';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { serviceSideProps } from '@/utils/i18n'; import { serviceSideProps } from '@/utils/i18n';
import { setToken } from '@/utils/user';
const RegisterForm = dynamic(() => import('./components/RegisterForm')); const RegisterForm = dynamic(() => import('./components/RegisterForm'));
const ForgetPasswordForm = dynamic(() => import('./components/ForgetPasswordForm')); const ForgetPasswordForm = dynamic(() => import('./components/ForgetPasswordForm'));
@@ -28,6 +29,7 @@ const Login = () => {
setLastChatAppId(''); setLastChatAppId('');
setUserInfo(res.user); setUserInfo(res.user);
setToken(res.token);
setTimeout(() => { setTimeout(() => {
router.push(lastRoute ? decodeURIComponent(lastRoute) : '/app/list'); router.push(lastRoute ? decodeURIComponent(lastRoute) : '/app/list');
}, 100); }, 100);

View File

@@ -1,9 +1,9 @@
import type { NextApiRequest } from 'next'; import type { NextApiRequest } from 'next';
import jwt from 'jsonwebtoken';
import Cookie from 'cookie'; import Cookie from 'cookie';
import { App, OpenApi, User, OutLink, KB } from '../mongo'; import { App, OpenApi, User, OutLink, KB } from '../mongo';
import type { AppSchema } from '@/types/mongoSchema'; import type { AppSchema } from '@/types/mongoSchema';
import { ERROR_ENUM } from '../errorCode'; import { ERROR_ENUM } from '../errorCode';
import { authJWT } from './tools';
export enum AuthUserTypeEnum { export enum AuthUserTypeEnum {
token = 'token', token = 'token',
@@ -11,26 +11,16 @@ export enum AuthUserTypeEnum {
apikey = 'apikey' apikey = 'apikey'
} }
export const parseCookie = (cookie?: string): Promise<string> => { export const authCookieToken = async (cookie?: string, token?: string): Promise<string> => {
return new Promise((resolve, reject) => {
// 获取 cookie // 获取 cookie
const cookies = Cookie.parse(cookie || ''); const cookies = Cookie.parse(cookie || '');
const token = cookies.token; const cookieToken = cookies.token || token;
if (!token) { if (!cookieToken) {
return reject(ERROR_ENUM.unAuthorization); return Promise.reject(ERROR_ENUM.unAuthorization);
} }
const key = process.env.TOKEN_KEY as string; return await authJWT(cookieToken);
jwt.verify(token, key, function (err, decoded: any) {
if (err || !decoded?.userId) {
reject(ERROR_ENUM.unAuthorization);
return;
}
resolve(decoded.userId);
});
});
}; };
/* auth balance */ /* auth balance */
@@ -117,8 +107,9 @@ export const authUser = async ({
return userId; return userId;
}; };
const { cookie, apikey, rootkey, userid, authorization } = (req.headers || {}) as { const { cookie, token, apikey, rootkey, userid, authorization } = (req.headers || {}) as {
cookie?: string; cookie?: string;
token?: string;
apikey?: string; apikey?: string;
rootkey?: string; rootkey?: string;
userid?: string; userid?: string;
@@ -130,13 +121,13 @@ export const authUser = async ({
let authType: `${AuthUserTypeEnum}` = AuthUserTypeEnum.token; let authType: `${AuthUserTypeEnum}` = AuthUserTypeEnum.token;
if (authToken) { if (authToken) {
uid = await parseCookie(cookie); uid = await authCookieToken(cookie, token);
authType = AuthUserTypeEnum.token; authType = AuthUserTypeEnum.token;
} else if (authRoot) { } else if (authRoot) {
uid = await parseRootKey(rootkey, userid); uid = await parseRootKey(rootkey, userid);
authType = AuthUserTypeEnum.root; authType = AuthUserTypeEnum.root;
} else if (cookie) { } else if (cookie || token) {
uid = await parseCookie(cookie); uid = await authCookieToken(cookie, token);
authType = AuthUserTypeEnum.token; authType = AuthUserTypeEnum.token;
} else if (apikey) { } else if (apikey) {
uid = await parseOpenApiKey(apikey); uid = await parseOpenApiKey(apikey);

View File

@@ -4,6 +4,7 @@ import crypto from 'crypto';
import jwt from 'jsonwebtoken'; import jwt from 'jsonwebtoken';
import { generateQA } from '../events/generateQA'; import { generateQA } from '../events/generateQA';
import { generateVector } from '../events/generateVector'; import { generateVector } from '../events/generateVector';
import { ERROR_ENUM } from '../errorCode';
/* 密码加密 */ /* 密码加密 */
export const hashPassword = (psw: string) => { export const hashPassword = (psw: string) => {
@@ -22,12 +23,24 @@ export const generateToken = (userId: string) => {
); );
return token; return token;
}; };
// auth token
export const authJWT = (token: string) =>
new Promise<string>((resolve, reject) => {
const key = process.env.TOKEN_KEY as string;
jwt.verify(token, key, function (err, decoded: any) {
if (err || !decoded?.userId) {
reject(ERROR_ENUM.unAuthorization);
return;
}
resolve(decoded.userId);
});
});
/* set cookie */ /* set cookie */
export const setCookie = (res: NextApiResponse, userId: string) => { export const setCookie = (res: NextApiResponse, token: string) => {
res.setHeader( res.setHeader(
'Set-Cookie', 'Set-Cookie',
`token=${generateToken(userId)}; Path=/; HttpOnly; Max-Age=604800; Samesite=None; Secure;` `token=${token}; Path=/; HttpOnly; Max-Age=604800; Samesite=None; Secure;`
); );
}; };
/* clear cookie */ /* clear cookie */

View File

@@ -331,6 +331,7 @@ const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
name: 'AI 对话', name: 'AI 对话',
flowType: FlowModuleTypeEnum.chatNode, flowType: FlowModuleTypeEnum.chatNode,
inputs: chatModelInput(formData), inputs: chatModelInput(formData),
showStatus: true,
outputs: [ outputs: [
{ {
key: 'answerText', key: 'answerText',
@@ -426,6 +427,7 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
{ {
name: '知识库搜索', name: '知识库搜索',
flowType: FlowModuleTypeEnum.kbSearchNode, flowType: FlowModuleTypeEnum.kbSearchNode,
showStatus: true,
inputs: [ inputs: [
{ {
key: 'kbList', key: 'kbList',
@@ -537,6 +539,7 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
name: 'AI 对话', name: 'AI 对话',
flowType: FlowModuleTypeEnum.chatNode, flowType: FlowModuleTypeEnum.chatNode,
inputs: chatModelInput(formData), inputs: chatModelInput(formData),
showStatus: true,
outputs: [ outputs: [
{ {
key: 'answerText', key: 'answerText',

View File

@@ -1,14 +1,23 @@
import { PRICE_SCALE } from '@/constants/common'; import { PRICE_SCALE } from '@/constants/common';
import { loginOut } from '@/api/user'; import { loginOut } from '@/api/user';
export const clearCookie = () => { const tokenKey = 'token';
export const clearToken = () => {
try { try {
loginOut(); loginOut();
localStorage.removeItem(tokenKey);
} catch (error) { } catch (error) {
error; error;
} }
}; };
export const setToken = (token: string) => {
localStorage.setItem(tokenKey, token);
};
export const getToken = () => {
return localStorage.getItem(tokenKey) || '';
};
/** /**
* 把数据库读取到的price转化成元 * 把数据库读取到的price转化成元
*/ */