mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-19 10:07:24 +00:00
perf: token
This commit is contained in:
@@ -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({
|
||||||
|
@@ -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)}`
|
||||||
);
|
);
|
||||||
|
1
client/src/api/response/user.d.ts
vendored
1
client/src/api/response/user.d.ts
vendored
@@ -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 {
|
||||||
|
@@ -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');
|
||||||
})();
|
})();
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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>) {
|
||||||
|
@@ -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);
|
||||||
|
@@ -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 cookieToken = cookies.token || token;
|
||||||
const token = cookies.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);
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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',
|
||||||
|
@@ -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,转化成元
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user