背景
在网页端使用微信第三方登录时,如果电脑已运行微信,网页会自动出现 “微信快捷登录” 选项,免去了掏出手机扫码的繁琐。趁着空闲时间研究了一下这玩意,这种静默感知的背后,实现逻辑非常巧妙。它利用了本地微信客户端作为临时的代理服务器,与浏览器进行跨进程通信,从而实现这种免扫码的登录体验。

技术拆解
端口枚举与本地服务探测
当你打开登陆页面时,网页前端并不知道微信客户端运行在哪个端口,于是他就会发起一系列的盲测,通过开发中工具的 Network 选项卡可以看到,网页会按顺序去尝试访问一系列特定的端口。

- 网页会反复调用
/api/check-login接口,如果接口返回成功,说明该端口是当前正在登陆的微信代理端口,否则说明当前没有微信正在登陆。 - 为了防止固定端口被占用,网页会按顺序尝试访问一系列特定的接口。
信息预获取
探测成功后,/api/check-login 会返回一些非敏感的用户信息:
- 展示数据:用户头像、昵称
- 临时凭证:一个生成的
authorize_uuid。
{
"nickname": "nickname",
"headimgurl": "headimgurl",
"authorize_uuid": "authorize_uuid"
}
注意,此处并没有发生真正的登陆,而且网页感知到了有微信正在运行。
唤起授权与 OAuth 握手
当用户点击 “微信快捷登陆” 按钮后,真正的 OAuth 流程才正式启动,具体流程:
- 唤起授权:网页前端会请求本地服务的
/api/authorize接口,微信客户端会弹起一个系统级的授权确认框。 - 用户确认:用户点击确认授权后,本地服务会颁发一个临时的
code,这个code并不会直接给你,而是携带在redirect_url上。 - 重定向:网页重定向至
redirect_url地址,随后后端通过常规的 OAuth 2.0 授权流程交换access_token并写入 Cookie。
深度思考
既然微信客户端暴露了监听接口,是否意味着任何网页都能探测我的微信状态,甚至窃取头像昵称?
通过实操可以发现,普通网页直接调用 /api/check-login 会直接触发跨域错误,查看微信接口的响应头可以发现关键:
Access-Control-Allow-Origin: https://open.weixin.qq.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
这是典型的跨域资源白名单保护,微信通过浏览器底层的同源策略,建立了一个只响应来自微信官方域名的本地服务。
那么新的问题来了,授权的第三方网页是如何跨源通信的?

通过分析发现,这实际上是一个官方 Iframe。当第三方网页加载登录插件时,脚本其实是运行在 open.weixin.qq.com 的上下文中。
当浏览器发起请求时,会根据当前执行脚本的域名自动带上 Origin: https://open.weixin.qq.com。
当 Iframe 内部完成了与本地微信的握手并拿到了携带 code 的 redirect_url ,怎么让外层的第三方网页进行登陆跳转呢?
这里有两种方案:
- 通信模式:使用
postMessage跨文档通信,通过window.parent.postMessage向外层发送信号,父页面监听该事件并根据传回的数据执行跳转。这种方式最安全,也最符合现代前端架构。 - 强制重定向:在 Iframe 内部使用
window.top强制重定向,优点是不需要父页面介入逻辑,Iframe 会直接通过window.top.location.href = redirect_url强行修改最外层浏览器窗口的地址。
通过对官方代码的溯源,发现其目前采用的是第二种方案,这种设计极大地降低了第三方开发者的集成难度。
总体流程
