扣子Coze实现ChatSDK的会话隔离(纯前端,萌新必看)

项目背景

使用coze提供的代码在网页插入智能体后,发现不同用户之间没有实现会话隔离(可以互相看到对话记录)。

虽然官方文档里也给了解决方案 ,但写的很粗略,对低代码用户非常不友好,而且示例代码给的还是python的,岂不是说要再部署个后端才能实现。

本文提供一个前端实现用户隔离的方案。

实现原理

先来看官方提供的代码:

<script src="https://lf-cdn.coze.cn/obj/unpkg/flow-platform/chat-app-sdk/1.2.0-beta.10/libs/cn/index.js"></script> <script> new CozeWebSDK.WebChatClient({ //创建一个智能体界面 config: { bot_id: '**********', // 智能体ID }, componentProps: { title: 'Coze', }, auth: { type: 'token', token: 'pat_********', // 访问令牌 onRefreshToken: function () { return 'pat_********' // 备用访问令牌,可以不填 } } }); </script>

由于coze是根据令牌来区分对话记录,而我们又把令牌写死在代码里,导致所有用户使用的是同一个令牌,看到的就是相同的对话记录。

也就是说,只要给不同用户发不同的令牌,就可以实现用户隔离了。

我们可以使用coze提供的OAuth应用来为每个用户自动申请新令牌,完整流程见下图。

流程对比

前期准备

需要准备以下四个东西:

  • 智能体 ID
  • OAuth ID
  • OAuth 公钥
  • OAuth 私钥

智能体

创建并发布智能体,智能体ID可以在地址栏里找到。

点开智能体,ID在地址栏里

OAuth

创建OAuth应用,类型为服务类应用,保存应用ID。

创建OAuth应用,类型为服务类应用

权限勾选 "Bot管理"、"会话管理"、"文件"、"消息"

设置权限

点击创建Key,保存生成的公钥和私钥,私钥文件用记事本打开即可

创建密钥

完整代码

js代码:

// 加载JWT生成库并初始化Coze智能体,替换你的配置后,加到网页的js里 (function() { // 配置参数(替换为你的实际信息) const COZE_CONFIG = { botId: '1145141145141', //智能体 ID appId: '*************',//OAuth ID publicKey: '******************************************************', //OAuth 公钥 privateKey:`-----BEGIN PRIVATE KEY----- ****************************************************** ****************************************************** -----END PRIVATE KEY-----` //OAuth 私钥,全复制进来 }; // 加载JWT库 function loadJwtLibrary() { return new Promise((resolve, reject) => { // 检查是否加载成功 if (window.KJUR && window.KJUR.jws && window.KJUR.jws.JWS) { resolve(); return; } const script = document.createElement('script'); script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/8.0.20/jsrsasign-all-min.js'; script.type = 'text/javascript'; script.crossOrigin = 'anonymous'; // 处理跨域问题 // 加载成功回调 script.onload = () => { // 验证库是否正确加载 if (window.KJUR && window.KJUR.jws && window.KJUR.jws.JWS) { resolve(); } else { reject(new Error('JWT库加载但未正确初始化')); } }; // 加载失败回调 script.onerror = () => { reject(new Error(`JWT库加载失败,请检查链接: ${script.src}`)); }; document.head.appendChild(script); }); } // 生成符合Coze要求的JWT function generateCozeJwt(userUid) { const header = { alg: 'RS256', typ: 'JWT', kid: COZE_CONFIG.publicKey }; const currentTime = Math.floor(Date.now() / 1000); const payload = { iss: COZE_CONFIG.appId, aud: "api.coze.cn", jti: Math.random().toString(36).substr(2, 32) + Date.now(), iat: currentTime, exp: currentTime + 3600, session_name: userUid }; const formattedPublicKey = COZE_CONFIG.privateKey; return window.KJUR.jws.JWS.sign( header.alg, JSON.stringify(header), JSON.stringify(payload), formattedPublicKey ); } // 获得Token并创建Coze智能体界面 async function getAccessToken(jwt) { try { const response = await fetch("https://api.coze.cn/api/permission/oauth2/token", { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${jwt}` }, body: JSON.stringify({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', duration_seconds: 900 }) }); if (!response.ok) { throw new Error(`获取token失败,HTTP状态码: ${response.status}`); } const data = await response.json(); new CozeWebSDK.WebChatClient({ config: { bot_id: COZE_CONFIG.botId }, componentProps: { title: 'Coze AI助手' }, auth: { type: 'token', token: data.access_token, onRefreshToken: () => data.access_token } }); } catch (error) { throw new Error(`获取Access Token失败: ${error.message}`); } } // 获取用户唯一标识 function getUserUid() { // 从本地存储获取登录用户ID const loggedUserId = localStorage.getItem('website_user_id'); if (loggedUserId) return loggedUserId; // 生成临时访客ID let visitorId = localStorage.getItem('coze_visitor_id'); if (!visitorId) { visitorId = `visitor_${Date.now()}_${Math.random().toString(36).slice(-6)}`; localStorage.setItem('coze_visitor_id', visitorId); } return visitorId; } // 初始化Coze聊天 function initCozeChat() { if (!window.CozeWebSDK || !window.CozeWebSDK.WebChatClient) { console.error('Coze SDK未加载'); return; } const userUid = getUserUid(); const jwtToken = generateCozeJwt(userUid); getAccessToken(jwtToken); } // 加载Coze SDK function loadCozeSdk() { const script = document.createElement('script'); script.src = "https://lf-cdn.coze.cn/obj/unpkg/flow-platform/chat-app-sdk/1.2.0-beta.10/libs/cn/index.js"; script.onload = initCozeChat; script.onerror = () => console.error(`Coze SDK加载失败: ${COZE_CONFIG.sdkSrc}`); document.head.appendChild(script); } // 初始化流程 async function init() { try { await loadJwtLibrary(); loadCozeSdk(); } catch (error) { console.error('初始化失败:', error.message); } } // 页面加载完成后初始化 if (document.readyState === 'complete') { init(); } else { window.addEventListener('load', init); } })();

把测试网页也贴一下,创建一个txt文件,把代码复制进去,再重命名为index.html,双击打开就可以了。

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Coze 智能体测试页面</title> </head> <body> <div> <div> <h1>Coze 智能体测试页面</h1> </div> </div> <script> //在此插入上述代码 </script> </body> </html>

成功的话应该会看到这样的界面,并且实现了用户对话隔离:

成功加载

安全问题

由于直接把公钥和私钥写在了js里,肯定有安全问题,但毕竟是全靠前端实现,不知道有啥解决方案( •̀ ω •́ )✧。

Read more

如何使用Dify搭建合同审查平台-法律文书机器人Agent?

在 Windows 系统中,基于 Dify 这个低代码 LLM 应用开发平台,从零搭建一个能解析合同、识别法律风险、给出修改建议的智能 Agent,全程覆盖环境部署、知识库构建、Agent 配置、功能测试的全流程。 第一阶段:Windows 环境准备(基础依赖安装) 步骤 1:安装 Python(Dify 运行基础) 1. 下载 Python:访问Python 官网,下载Python 3.10+ 版本(推荐 3.10.11,兼容性最好)。 2. 安装注意: * 勾选「Add Python 3.10 to PATH」

Gazebo 机器人三维物理仿真平台

Gazebo 简介 Gazebo 是一款由 Open Robotics(前身为 Willow Garage 和 OSRF)开发的开源 3D 机器人仿真软件。它是目前世界上最流行的机器人仿真平台之一,被广泛应用于学术研究、工业开发和机器人竞赛中。 核心特性 1. 物理仿真引擎 * ODE(Open Dynamics Engine):默认物理引擎,支持刚体动力学 * Bullet:支持软体动力学和复杂碰撞检测 * Simbody:生物力学级精确仿真 * DART:基于广义坐标的高效动力学仿真 2. 3D 图形渲染 * OGRE(Object-Oriented Graphics Rendering Engine):提供高质量的 3D 可视化 * 支持逼真的光照、阴影、材质和纹理 * 可配置多摄像头视角和传感器可视化 3. 传感器仿真 支持多种机器人传感器的仿真:

AI无人机赋能乡村道路管护构建智慧交通的“最后一公里“新范式,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建公共交通道路场景下路面缺陷病害智能化检测预警系统

AI无人机赋能乡村道路管护构建智慧交通的“最后一公里“新范式,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建公共交通道路场景下路面缺陷病害智能化检测预警系统

在乡村振兴战略的推进过程中,"村村通"工程作为连接城乡的重要纽带,已实现全国98%以上的行政村通硬化路。然而,随着农村公路里程的快速增长,传统人工巡检模式逐渐暴露出效率低、覆盖难、响应慢等痛点。当AI技术遇上低空无人机,一场乡村道路管护的智能化革命正在悄然发生,为破解农村交通治理难题提供了创新方案。 一、传统巡检之困:乡村道路管护的"阿喀琉斯之踵" 农村公路具有"点多、线长、面广"的典型特征,全国农村公路总里程已突破450万公里。传统人工巡检模式下,养护队伍需定期徒步或驾车巡查,日均巡检里程不足20公里,且受地形限制,桥梁涵洞、临水临崖等特殊路段存在巡检盲区。某农业大省调研显示,农村公路病害发现平均滞后周期达47天,裂缝发展成坑槽的比例高达63%,直接导致养护成本增加3-5倍。 更严峻的是,农村地区技术人才短缺,巡检人员平均年龄超过50岁,对裂缝宽度、沉陷深度等关键指标的判断依赖经验,数据记录仍采用纸质台账,难以实现病害发展的动态追踪。这种"被动式"

Modelsim仿真软件的,安装/破解/使用教程大全

仿真前言         作为一名FPGA工程师,在做FPGA开发时,使用仿真一定是最重要的,有些人喜欢写完代码直接上板子调试,根本不会做一点点仿真;如果是简单的逻辑代码,有十足的把握,那就不用仿真,可以直接上板子调试,但是,如果您是在做工程的开发,很多代码都是第一次编写调试,那么,代码的仿真是一定要做的,你要问我为啥,我个人觉得,每次把自己写完的代码,放到modelsim上面仿真看一下波形,就像考试的时候,拿着参考答案在做题一样的感觉,各个波形的变化你都会看的一清二楚,但是如果你用在线逻辑分析仪看RTL的仿真,那真的是太耗费时间;         我知道这个时候就会有人说了,Modelsima仿真有啥用呀,和下板子调试完全是两个概念,包括信号延迟,信号质量,眼图等都不一样,说的也对,但是实际情况是,这些人眼高手低,觉得仿真这种操作太麻烦;仿真虽然不能完全模拟真实的硬件信号,硬件延迟也没法准确仿真,但是他能让你在开发的时候,规避掉95%的因为代码引起的错误,这会让你在调试阶段节省很多时间;然后剩下的调试你必须 要在硬件调试时才会发现并且解决;        在调试阶段,FPGA为