聚合登录
测试站:www.chengbuwan.com
为 Halo 博客接入微信、QQ、支付宝登录。访客可以用三方账号直接登录,也可以在个人中心绑定已有账号,用法和 Halo 官方的 GitHub 登录插件一样。
功能
- 支持微信、QQ、支付宝三种登录方式,登录页自动显示对应图标
- 首次三方登录时,Halo 会打开选择页:已有账号选绑定登录,没有账号选注册新账号(站点需开启允许注册并设置默认角色);注册后下次直接登录
- 已登录用户可以在个人中心绑定或解绑三方账号
- 每次授权生成一次性随机校验码(state),回调时一次性校验,防 CSRF 与账号接管
- 登录会话、记住我、登录日志均由 Halo 核心管理
- 微信、QQ、支付宝图标内置,无需额外配置
安装
- 在 Releases 下载
juhedenglu-1.0.2.jar - 打开 Halo Console → 插件 → 安装,上传 JAR 并启用插件
- 在聚合登录服务商后台登记回调地址(见下节),获取 AppID 和 AppKey
- 打开 Halo Console → 用户 → 身份认证,启用 微信、QQ、支付宝
- 打开 Halo Console → 插件 → 聚合登录 → 设置,填入 AppID 和 AppKey,拉到页面最下方点 保存
AppID 和 AppKey 只在你自己的 Console 里填写,请勿发给他人,也不要写进代码或文档。
回调地址
在聚合登录服务商后台登记以下回调地址:
https://你的域名/login/mapay/callback
例如你的站点是 https://example.com,就登记 https://example.com/login/mapay/callback。
每次授权时,插件会在回调地址后面加一段一次性随机码,实际回跳地址形如 https://你的域名/login/mapay/callback/AbCdEf1234...?type=wx&code=...。服务商按原样回跳即可,不需要把随机码那段也登记进去;这段码只在当次授权有效,回调校验一次后即失效。
插件设置里还有两个可选项,一般不用改:
- 聚合登录服务地址:默认为
https://login.mapay.cn,使用其他聚合登录服务时再改 - 站点对外地址:留空时自动使用 Halo 配置的外部访问地址;如果站点在反向代理后面,或想用另一个域名做回调,在这里填写,如
https://你的域名(不要带末尾斜杠)
使用方法
访客登录:在登录页点微信、QQ 或支付宝图标,完成三方授权后回到本站。第一次用某个三方账号登录时,Halo 会打开一个选择页:已有本站账号的选「绑定已有账号」,没有账号的选「注册新账号」;注册新账号需要站点开启「允许注册」并设置默认角色(不能是超级管理员)。如果站点关闭了注册,选择页只提供绑定已有账号。注册时昵称、头像取自三方资料,不会拿到邮箱。
绑定账号:登录后进入个人中心,在绑定设置里点微信、QQ 或支付宝,完成授权后即与当前账号绑定;解绑后可以重新绑定。
常见问题
点绑定后直接跳回个人中心,没有去三方授权页?
授权发起失败时会显示错误页并写明原因。最常见的是插件设置填完没有点保存(保存按钮在设置页最下方);其次是 AppID 或 AppKey 填错,或服务器连不上聚合登录服务。
用三方登录创建的账号没有邮箱?
聚合登录服务不返回邮箱,因此这类账号没有已验证邮箱,不能用邮箱登录或找回密码。
新用户登录失败?
请确认 Halo 已开启「允许注册」,并设置了默认角色(不能是超级管理员)。关闭注册时,新用户无法通过三方登录创建账号,只能绑定已有账号。
昵称是中文,用户名变成了一串随机字符?
中文昵称不符合 Halo 用户名规则时,Halo 会自动生成 user-xxxxxxxx 形式的用户名,显示名仍使用你的昵称。
授权和回跳要在同一个浏览器里完成
每次授权都会生成一段一次性随机码,存在当前浏览器会话里,回调时一次性校验。发起登录和授权回跳必须在同一个浏览器会话中进行;换浏览器、使用无痕窗口、中途清掉会话,或打开别人伪造的回调链接,回跳都会被拒绝,需要重新发起登录。
隐私说明
本插件会连接外部聚合登录服务完成微信、QQ、支付宝登录。
- 服务:聚合登录服务,默认地址为
https://login.mapay.cn。插件设置里的“聚合登录服务地址”可以改成其他兼容的服务地址,实际使用的以你的设置为准。 - 用途:仅用于发起三方登录授权、换取三方用户信息。插件不做统计、不做遥测、不投放广告、不追踪用户。
- 发送给服务的数据:AppID、AppKey、回调地址(
https://你的域名/login/mapay/callback/{一次性随机码})、授权成功后服务返回的 code。按服务官方文档,接口仅支持 GET 请求,AppKey 作为 URL 请求参数经 HTTPS 发送;插件不会在日志、错误页或异常信息中记录完整请求地址或 AppKey。 - 从服务接收的数据:对方账号 ID(social_uid)、昵称、头像地址、性别、所在地。
- 写入 Halo 的数据:Halo 核心据此创建用户(用户名、显示名、头像)并创建用户连接(登录方式 + 对方账号 ID)。插件本身不在数据库、文件或日志中保存任何用户信息;AppID 和 AppKey 只保存在 Halo 的插件设置里。每次授权的一次性随机码只保存在当前浏览器会话中,回调校验一次后即失效,不写入数据库、文件或日志。
- 解绑与删除:在个人中心解绑会删除对应的用户连接;删除 Halo 用户时,其用户连接会一并删除(Halo 核心行为)。卸载插件后,已创建的用户账号和绑定关系仍保留在 Halo 中,插件不会删除它们;但微信、QQ、支付宝登录入口会消失,此前仅通过三方登录的账号将无法再用三方登录,需要管理员在 Console 中处理。
- 数据保存位置和期限:用户数据保存在你自己的 Halo 数据库中,保存期限由你控制;服务商一侧的数据处理以服务商的隐私政策为准。
派生来源
本插件参考 halo-sigs/plugin-oauth2(GPL-3.0)的 AuthProvider 扩展与 OAuth2AuthenticationToken 交接方式独立实现,不是直接从上游仓库 fork 复制代码,因此没有可对应的上游提交;仓库为新建仓库,许可证保持 GPL-3.0,署名与许可证信息见本 README 末尾与 LICENSE。
上游贡献记录:无。原因:上游是通用 OAuth2 客户端(标准授权码 + token + userinfo 流程),本插件对接的是非标准聚合登录协议(Mapay 的 GET connect.php 流程,没有 token 端点和 userinfo 端点),这类改动无法以通用修复的形式合入上游,也不属于适合先向上游贡献的通用增强。
与上游的具体差异:
- 协议不同:上游是标准 OAuth2,本插件对接 Mapay 非标准聚合登录:
GET connect.php?act=login取跳转链接,三方授权后回调 code,再GET connect.php?act=callback换用户信息。上游无法通过配置实现这种流程。 - 登录厂商不同:上游需用户自行到各平台注册 OAuth 应用再逐个配置;本插件内置微信、QQ、支付宝三个入口与图标,用户只需填一个聚合服务的 AppID 和 AppKey。
- 回调实现不同:上游使用 Spring Security OAuth2 client;本插件使用自有 WebFilter + WebSession,每次授权生成不可预测的一次性 state(32 字节随机数),放在回调地址路径里,回调时一次性校验。
- 设置不同:新增聚合登录服务地址、站点对外地址两项可配置项;AppKey 为明文输入框(与 AppID 一致)。
- 使用场景不同:面向中文个人站长,没有条件分别注册微信、QQ、支付宝开放平台应用的场景,上游不覆盖这一场景。
维护计划:跟随 Halo 2.20 以上版本(当前以 2.27 为准)适配 AuthProvider 机制变更;安全问题随报随修;上游协议或 Halo 认证机制变更时同步适配;用户支持通过 GitHub Issues 响应。
更新日志
1.0.2
- 安全修复:每次授权生成不可预测的一次性 state(32 字节随机数),放在回调地址路径里(
/login/mapay/callback/{state}),回调时与当前浏览器会话一次性校验(常数时间比较),校验不通过的 code 不会用于登录或绑定。修复 1.0.1 的 CSRF 漏洞:此前仅校验会话发起过同类型授权,攻击者可用自己的授权 code 诱导已登录用户打开攻击者回调地址,把攻击者的三方身份绑定到受害者账号导致账号接管(Halo 应用市场审核在 2.27.1 实机复现) - README 按 Halo 2.27.1 实测行为重写:首次登录是 Halo 的选择页(绑定已有账号 / 注册新账号),不是自动创建账号;回调地址说明一次性随机码;安装链接指向 1.0.2 的 JAR
- 补充许可证与派生来源说明:GPL-3.0、上游 halo-sigs/plugin-oauth2、与上游的具体差异及维护计划
1.0.1
- 修复微信登录回调:聚合登录服务回跳时 type=wx,之前会被拒绝导致微信登录和绑定失败
- Java 包名由
run.halo.mapay改为com.chengbuwan.mapay - 新增隐私说明;日志不再记录异常详情,避免泄露请求地址或 AppKey
1.0.0
- 首次发布:微信、QQ、支付宝聚合登录,支持登录与个人中心绑定
从源码构建
需要 Java 21:
./gradlew build
构建产物在 build/libs/juhedenglu-1.0.2.jar。
问题反馈
遇到问题或有改进建议,欢迎在 Issues 提交。
开源协议
本项目遵循 GPL-3.0 开源协议;参考了 halo-sigs/plugin-oauth2(同样为 GPL-3.0)的实现方式。微信、QQ、支付宝的图标为各平台官方标识,版权归各自权利人所有,仅用于登录入口展示。
