聊天数据加密

This commit is contained in:
冯辉
2026-04-30 14:55:25 +08:00
parent af800b4f63
commit 7aa8761ea8

View File

@@ -1,5 +1,6 @@
import config from "@/config.js" import config from "@/config.js"
import useUserStore from '@/stores/useUserStore'; import useUserStore from '@/stores/useUserStore';
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
/** /**
* @param url String请求的地址默认none * @param url String请求的地址默认none
@@ -25,6 +26,14 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom
const userStore = useUserStore(); const userStore = useUserStore();
const Authorization = userStore.token ? encodeURIComponent(userStore.token) : ''; const Authorization = userStore.token ? encodeURIComponent(userStore.token) : '';
const requestBody = data && Object.keys(data).length > 0
? {
encrypted: true,
encryptedData: sm4Encrypt(config.sm4Config.key, JSON.stringify(data)),
timestamp: Date.now(),
}
: data;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let buffer = ''; let buffer = '';
let hasReceivedContent = false; let hasReceivedContent = false;
@@ -32,7 +41,7 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom
const requestTask = uni.request({ const requestTask = uni.request({
url: config.StreamBaseURl + url, url: config.StreamBaseURl + url,
method: 'POST', method: 'POST',
data: data, data: requestBody,
header: { header: {
"Authorization": Authorization, "Authorization": Authorization,
"Accept": "text/event-stream", "Accept": "text/event-stream",
@@ -179,9 +188,20 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom
if (jsonData && jsonData.trim()) { if (jsonData && jsonData.trim()) {
try { try {
const parsedData = JSON.parse(jsonData); let parsedData = JSON.parse(jsonData);
console.log('🔧 解析后的JSON:', parsedData); console.log('🔧 解析后的JSON:', parsedData);
if (parsedData?.encrypted && typeof parsedData?.encryptedData === 'string') {
const decryptedStr = sm4Decrypt(config.sm4Config.key, parsedData.encryptedData);
if (decryptedStr && decryptedStr !== parsedData.encryptedData) {
try {
parsedData = JSON.parse(decryptedStr);
} catch (e) {
console.error('SSE解密数据JSON解析失败:', e.message);
}
}
}
// 检查是否有错误信息 // 检查是否有错误信息
const finishReason = parsedData?.choices?.[0]?.finish_reason; const finishReason = parsedData?.choices?.[0]?.finish_reason;
if (finishReason === "error") { if (finishReason === "error") {
@@ -279,12 +299,21 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) {
"Accept": "text/event-stream", "Accept": "text/event-stream",
"Content-Type": "application/json;charset=UTF-8" "Content-Type": "application/json;charset=UTF-8"
}; };
const requestBody = data && Object.keys(data).length > 0
? {
encrypted: true,
encryptedData: sm4Encrypt(config.sm4Config.key, JSON.stringify(data)),
timestamp: Date.now(),
}
: data;
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
const response = await fetch(config.StreamBaseURl + url, { const response = await fetch(config.StreamBaseURl + url, {
method: "POST", method: "POST",
headers, headers,
body: JSON.stringify(data) body: JSON.stringify(requestBody)
}); });
if (!response.ok) { if (!response.ok) {
@@ -347,9 +376,21 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) {
try { try {
// 检查JSON数据是否完整 // 检查JSON数据是否完整
if (jsonData && jsonData.trim() && jsonData !== "[DONE]") { if (jsonData && jsonData.trim() && jsonData !== "[DONE]") {
const parsedData = JSON.parse(jsonData); let parsedData = JSON.parse(jsonData);
console.log('🔧 解析后的JSON:', parsedData); console.log('🔧 解析后的JSON:', parsedData);
if (parsedData?.encrypted && typeof parsedData?.encryptedData === 'string') {
const decryptedStr = sm4Decrypt(config.sm4Config.key, parsedData.encryptedData);
if (decryptedStr && decryptedStr !== parsedData.encryptedData) {
try {
const decrypted = JSON.parse(decryptedStr);
parsedData = decrypted;
} catch (e) {
console.error('SSE解密数据JSON解析失败:', e.message);
}
}
}
// 检查是否有错误信息 // 检查是否有错误信息
const finishReason = parsedData?.choices?.[0]?.finish_reason; const finishReason = parsedData?.choices?.[0]?.finish_reason;
if (finishReason === "error") { if (finishReason === "error") {
@@ -458,9 +499,21 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) {
console.log('📄 提取的剩余JSON数据:', jsonData); console.log('📄 提取的剩余JSON数据:', jsonData);
if (jsonData && jsonData !== "[DONE]") { if (jsonData && jsonData !== "[DONE]") {
try { try {
const parsedData = JSON.parse(jsonData); let parsedData = JSON.parse(jsonData);
console.log('🔧 解析后的剩余JSON:', parsedData); console.log('🔧 解析后的剩余JSON:', parsedData);
if (parsedData?.encrypted && typeof parsedData?.encryptedData === 'string') {
const decryptedStr = sm4Decrypt(config.sm4Config.key, parsedData.encryptedData);
if (decryptedStr && decryptedStr !== parsedData.encryptedData) {
try {
const decrypted = JSON.parse(decryptedStr);
parsedData = decrypted;
} catch (e) {
console.error('SSE解密数据JSON解析失败:', e.message);
}
}
}
// 检查是否有错误信息 // 检查是否有错误信息
const finishReason = parsedData?.choices?.[0]?.finish_reason; const finishReason = parsedData?.choices?.[0]?.finish_reason;
if (finishReason === "error") { if (finishReason === "error") {
@@ -573,33 +626,49 @@ export function chatRequest(url, data = {}, method = 'GET', loading = false, hea
const header = headers || {}; const header = headers || {};
header["Authorization"] = encodeURIComponent(Authorization); header["Authorization"] = encodeURIComponent(Authorization);
const isEncryptedMethod = method.toUpperCase() === 'POST' || method.toUpperCase() === 'PUT';
const requestData = isEncryptedMethod && data && Object.keys(data).length > 0
? {
encrypted: true,
encryptedData: sm4Encrypt(config.sm4Config.key, JSON.stringify(data)),
timestamp: Date.now(),
}
: data;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.request({ uni.request({
url: config.StreamBaseURl + url, url: config.StreamBaseURl + url,
method: method, method: method,
data: data, data: requestData,
header, header,
success: resData => { success: resData => {
// 响应拦截
if (resData.statusCode === 200) { if (resData.statusCode === 200) {
let responseData = resData.data;
try {
if (responseData?.encrypted) {
const decrypted = sm4Decrypt(config.sm4Config.key, responseData.encryptedData);
responseData = JSON.parse(decrypted);
}
} catch (e) {
console.error('[chatRequest] 解密失败:', e.message);
}
const { const {
code, code,
msg msg
} = resData.data } = responseData
if (code === 200) { if (code === 200) {
resolve(resData.data) resolve(responseData)
return return
} }
uni.showToast({ uni.showToast({
title: msg || '请求失败', title: msg || '请求失败',
icon: 'none' icon: 'none'
}) })
// 拒绝Promise并提供详细错误信息
const err = new Error(msg || '请求失败,服务器返回错误码: ' + code) const err = new Error(msg || '请求失败,服务器返回错误码: ' + code)
err.error = resData err.error = resData
reject(err) reject(err)
} else { } else {
// 处理非200状态码
const errorMsg = `请求失败HTTP状态码: ${resData.statusCode}` const errorMsg = `请求失败HTTP状态码: ${resData.statusCode}`
uni.showToast({ uni.showToast({
title: errorMsg, title: errorMsg,