news 2026/8/24 14:53:28

AI 软件开发实战教程(十二):安全地交换双方微信号

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI 软件开发实战教程(十二):安全地交换双方微信号

“AI 软件开发实战教程”系列第 12 篇:让候选中的一方主动确认后,双方同时获得对方微信号,同时保证确认前不泄露、重复点击不重复、资料修改不改写历史。

系统找到“可能同路”的人以后,真正的沟通仍要回到微信。邻行不做站内聊天,因此联系方式交换是第一条核心流程中风险最高的一步。

如果只把微信号显示在候选详情里,会出现三个问题:用户没有明确同意把自己的联系方式给对方;页面权限的一处疏漏就可能批量泄露;用户修改微信号后,过去已经交换的结果会悄悄变化。

K4 先把交换定义成一个独立、不可覆盖的业务事实。

“双向交换”不是“双向审批”

产品规则是:候选双方中的任何一方都可以发起。确认页必须明确告诉发起者:

确认后,你会看到对方的微信号; 你的微信号也会同时提供给对方。 这只是方便双方回微信沟通, 不代表已经约定同行。

对方不需要再点一次同意。因此页面不能写成“双向确认”,否则发起者会误以为还要等待。

一次操作同时披露,是这个产品在小范围社区场景中的明确选择。它减少了双方异步上线造成的等待,但也要求确认文案、权限复核和审计事实都足够清楚。

红灯先固定授权边界

K4 的第一组测试在导入阶段失败,因为交换模型和服务还不存在。随后测试逐个固定这些拒绝条件:

  • 操作者不是候选双方之一;
  • 任一方账户被限制或不可用;
  • 候选已经失效;
  • 任一出行信息已经关闭、取消或过期;
  • 已到双方较早的预计出发时间;
  • 双方不再属于同一个社区;
  • 任一方尚未设置微信号。

交换服务不相信用户刚刚打开的候选页面。点击确认到请求抵达服务器之间,状态可能已经改变,所以服务会在短事务中重新锁定和检查候选及双方信息。

一个容易混淆的边界是匹配截止。它只表示停止产生新候选。截止前已经形成的候选,即使现在已经停止匹配,只要双方尚未到较早预计出发时间,仍然可以交换微信号。专门的注入时钟测试固定了这条规则。

保存“当时披露的值”

交换不能只保存两个用户 ID,然后每次打开页面去读取最新个人资料。

假设乘客交换时的微信号是wx_old,后来改成wx_new。过去的车主已经拿到wx_old,系统却显示wx_new,历史事实就不再可信。

因此ContactExchange保存:

候选 发起者 交换时间 车主当时微信号的加密快照 乘客当时微信号的加密快照 密钥版本

服务先用个人资料对应版本的密钥解密,再用当前活动密钥重新加密为交换快照。测试在交换后修改乘客资料,旧结果仍必须返回交换时的值。

这里保存快照不是为了无限保留。账户删除任务仍要按产品规则擦除该用户在在线资料和交换快照中的敏感值,那属于后续 K8 的数据生命周期工作。

一对一约束是幂等的最后防线

同一个候选只能有一次联系方式交换。数据模型使用候选的一对一关系,事务中也先返回已经存在的结果。

测试让车主先发起,再由乘客重复发起,最终只能得到:

1 个 ContactExchange 1 个 contact.exchanged 业务事件 双方各 1 条站内提醒 双方各 1 条渠道投递记录

无论双击按钮、网络重试,还是双方几乎同时操作,业务语义都不会变成交换两次。

SQLite 上的测试可以证明顺序重试和数据库唯一事实。真正的 PostgreSQL 双连接并发仍应在具备服务环境时补跑,当前机器没有 PostgreSQL,不能把 SQLite 冒充并发证据。

不要把秘密交给模板再隐藏

一个常见但危险的做法,是把车主和乘客的微信号都放入模板上下文,然后用页面条件决定显示哪一个。

隐藏的 DOM、调试输出、错误页或以后新增的前端序列化,都可能把不该出现的值送到浏览器。

邻行的结果服务先判断当前查看者身份:

查看者是车主 → 只解密乘客快照 查看者是乘客 → 只解密车主快照 其他人 → 拒绝

模板上下文只有一个other_wechat_id。HTTP 测试分别断言:

  • 确认页源码不包含双方任一微信号;
  • 交换后页面包含对方微信号;
  • 页面不包含自己的微信号;
  • 页面不包含登录账号;
  • 非参与者打开确认和结果地址都得到 404。

安全边界应当尽量发生在数据进入表现层之前,而不是依赖 CSS 或前端脚本隐藏。

复制按钮必须允许失败

微信内置浏览器、系统权限和非安全上下文都可能让 Clipboard API 不可用。一键复制只能是增强能力,不能成为唯一出口。

结果页把对方微信号放在只读但可以聚焦、长按和选择的输入框中。复制成功显示“已复制”;失败时自动选中文本并提示:

复制失败,请长按或手动选择上面的微信号。

页面不会尝试打开未知的微信协议,也不会自动跳走。下一步文案只告诉用户返回微信添加对方并确认具体上下车位置。

自动浏览器可以证明结构和降级路径已经存在,但 iOS 和 Android 微信中的长按选择、复制权限与返回操作,仍必须由 Gate B 真机验收,不能由桌面 Chromium 最终代替。

双用户浏览器闭环

K3 已有两个隔离浏览器上下文。K4 在同一旅程后继续执行:

乘客打开候选 → 点击“想和对方联系” → 确认页看不到任何微信号 → 阅读互相披露说明并确认 → 乘客只看到车主微信号 → 车主刷新候选并打开结果 → 车主只看到乘客微信号 → 双方都看到返回微信的下一步

两个上下文有独立 Cookie 和会话。测试不是把同一个客户端来回切换用户,因此更接近双方异步操作的真实授权路径。

本节点结果

K4 收口时:

  • 85 个非浏览器测试通过;
  • 分支覆盖率 90.79%;
  • Ruff、格式、mypy strict、迁移和 Django 检查通过;
  • 4 条 Chromium 旅程通过,其中双用户旅程已走到互相披露结果;
  • 重复交换、资料修改、非参与者、受限账户、失效状态和时间边界都有自动证据;
  • 确认前不含微信号,结果页每人只收到对方微信号;
  • 外部提醒实际发送、PostgreSQL 并发、WebKit 和微信真机仍未宣称通过;
  • 结果只形成本地提交,不推送。

验收矩阵中,AC-21 至 AC-23 可以在当前页面范围内自动通过,AC-41 也完成交换前后身份展示闭环。AC-24 仍是部分通过:交换事实与双方独立投递记录已经形成,第三方一方失败不影响另一方要等 K7 故障发送测试。

写在最后

敏感数据功能的关键,不是“加密了”三个字,而是明确谁在什么时刻授权、事务中重新检查什么、保存哪个时间点的值,以及秘密最早在哪一层被裁剪。

当结果模板从一开始就只拿到对方微信号,后续页面改版也更难意外泄露另一份数据。好的隐私设计往往同时让代码职责更清晰。

下一篇进入 K5:双方回微信沟通后怎样分别反馈结果,为什么单方确认不能占座,以及如何用数据库锁保证最后一个座位不会同时分给两位乘客。

关键代码与操作

下面的简化测试从双方视角读取同一次交换,证明每个人只能得到对方的微信号:

deftest_one_actor_discloses_both_contacts(candidate,driver,passenger):exchange=exchange_contact(candidate_id=candidate.pk,actor_id=driver.pk,now=timezone.now(),)assertget_disclosed_contact(exchange=exchange,viewer=driver)=="passenger-wechat"assertget_disclosed_contact(exchange=exchange,viewer=passenger)=="driver-wechat"assertBusinessEvent.objects.filter(event_type="contact.exchanged").count()==1

验证命令:make bugfix TEST=tests/matching/test_contact_exchange.py::test_one_actor_discloses_both_contacts_and_creates_one_event

示例只表达权限方向;真实测试还会覆盖重复点击、资料修改、外部成员和过期候选。

本篇验证摘要

  • 双方必须在同一个有效候选中明确同意互相披露,系统才创建交换;
  • 交换保存当时双方微信号的加密快照,之后修改资料不会悄悄改写历史结果;
  • 唯一约束和幂等服务保证重复点击不会创建第二次交换;
  • 查询服务只向每位参与者返回对方的联系方式,页面拿不到自己的解密值;
  • 移动浏览器已验证双方确认、查看和复制流程,提醒码始终不会进入页面。

附录:相关工具与仓库

gstack

仓库:garrytan/gstack
地址:https://github.com/garrytan/gstack

dev-harness

仓库:Dev-Wiki/dev-harness
地址:https://github.com/Dev-Wiki/dev-harness

UI UX Pro Max Skill

仓库:nextlevelbuilder/ui-ux-pro-max-skill
地址:https://github.com/nextlevelbuilder/ui-ux-pro-max-skill

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 14:52:49

[特殊字符] DocxTableExport:一键提取 Word 文档中的表格数据

功能特性: 提取 Word 文档中的所有或指定表格支持水平合并单元格 (GridSpan)支持垂直合并单元格 (vMerge)支持嵌套表格提取(可开关)自动识别数字和日期格式(可开关)自动调整列宽(可开关)自动筛选…

作者头像 李华
网站建设 2026/8/24 14:51:28

单词汇总(一)

1.Embedded System 嵌入式系统2.IC ‌Integrated Circuit‌ 集成电路3.stack栈 heap堆4.welcome to board 欢迎加入5.TTS Text to speech 文字转换成语音6.designer 设计师7.co-work 合作8.FPGA Field Programmable Gate Array 现场可编程门阵列,是一种用户可编程的半导体集成…

作者头像 李华
网站建设 2026/8/24 14:46:53

##关于Java中多态部分知识点##

一、多态父类引用指向不同的子类对象,调用同一个方法时,表现出不同的行为,这就叫多态。需要有向上转型的操作。例:Animal(父类) animal new Dog(子类)("小黄", 10);子类必…

作者头像 李华
网站建设 2026/8/24 14:43:26

处暑:一场盛大的告别

风,是从昨夜开始变的。起初只是一丝若有若无的凉意,从窗缝里钻进来,轻轻拂过脚踝。你翻了个身,把搭在床尾的薄被往上拉了拉 —— 这个动作,整个夏天都没有做过。醒来时,阳光依旧明亮,但落在皮肤…

作者头像 李华
网站建设 2026/8/24 14:42:54

✨ Mac 版微信防撤回软件:原理、安装与使用全攻略

【Mac 微信防撤回】 适用于 Apple Silicon Mac,通过本地客户端补丁实现: 对方撤回消息后,原消息仍保留 自己发送的消息可以正常撤回 对方撤回时显示提示 修改前自动备份,支持恢复和移除补丁 完全本地运行,不读取聊天数…

作者头像 李华
网站建设 2026/8/24 14:42:05

2026年降重降AI二合一工具测评:5款实测打分

毕业论文查重和AI检测双重收紧,毕业生一边改重复率一边躲AIGC标记,单靠人工熬夜硬扛效率太低。这次我花了两周时间,用同一篇模拟论文对5款降重降AI二合一工具做了实测打分,重点看双检通过率到底差多少。 为什么降重降AI必须一起处…

作者头像 李华