外观
网站扫码登录(kglogin.js)
对标微信网站应用扫码登录:第三方 PC 网站引入 kglogin.js,在自己的登录页里内嵌一个「用 Kango App 扫码登录」的二维码。用户用 Kango App「扫一扫」扫码、在手机上确认后,浏览器整页跳到你的 redirect_uri?code=&state=。
拿到 code 之后的换 token、拉用户信息、验 id_token,以及前置准备、scope、错误码,与授权页跳转完全相同,见 OAuth 2.0 授权登录。
用法、参数名与微信的 wxLogin.js 保持一致,从微信迁过来只需换脚本地址和 appid。
测试页
apisvc/jssdk/kglogin-demo.html 是一个纯前端测试页(AppSecret 填在网页里,只为一个文件跑通),拷到任意 web 服务器即可测。正式接入请参照 服务端完整示例(Go / PHP)。
流程
text
第三方网站(PC 浏览器) Kango 平台 用户手机(Kango App)
│
│ 1. 引入 kglogin.js,new KgLogin({...})
│ 内嵌 iframe:/jssdk/qrconnect.html
├─────────────────────────────►
│ 2. 校验 appid / redirect_uri
│ 出二维码(3 分钟有效)
│ ◄──────────────────────────── 3. 「扫一扫」扫码
│ iframe 显示「扫描成功」 确认页展示网站名称、
│ 申请的权限、请求 IP
│ ◄──────────────────────────── 4. 点「确认登录」
│ 5. 顶层窗口跳转 redirect_uri?code=xxx&state=xxx
◄─────────────────────────────┤
│
│ 6. 你的服务端:POST /api/oauth/token(code + client_id + client_secret)
│ 7. 你的服务端:GET /api/oauth/userinfo(Bearer access_token)第 1 步:页面内嵌二维码
html
<div id="login_container"></div>
<script src="https://kg.citv.cc/jssdk/kglogin.js"></script>
<script>
var obj = new KgLogin({
id: "login_container", // 二维码容器 id
appid: "YOUR_APP_KEY", // H5APP 的 AppKey
scope: "openid profile",
redirect_uri: "https://your-site.com/kango/callback",
state: "由你的服务端生成的随机串", // 回跳时原样带回,用于防 CSRF
});
</script>二维码以 iframe 形式渲染,默认 300×400;失效或用户取消后,在 iframe 内点击即可刷新。
参数
| 参数 | 必填 | 说明 |
|---|---|---|
id | 是 | 页面中放置二维码的容器 id |
appid | 是 | H5APP 的 AppKey(也可写 client_id) |
redirect_uri | 是 | 回调地址,须已登记(见前置准备)。微信要求调用方先 encodeURIComponent,这里编码与不编码两种写法都接受 |
state | 推荐 | 随机串,回跳时原样返回。务必由服务端生成并存入用户会话,回调时比对,防 CSRF |
scope | 否 | 空格分隔,默认 openid profile。写微信的 snsapi_login 等同 openid profile unionid。实际授予范围再按应用登记的 scopes 收敛 |
self_redirect | 否 | true:在 iframe 内部跳转 redirect_uri;默认 false:顶层窗口跳转 |
style | 否 | black(默认,深色文字,用于浅色背景)/ white(浅色文字,用于深色背景) |
href | 否 | 占位:微信用它注入自定义 CSS,Kango 不接受外部样式,传了忽略 |
code_challenge | 条件 | PKCE 挑战值(仅 S256)。机密客户端可不传;公开客户端(AppType=1)必须传,换 token 时带 code_verifier |
code_challenge_method | 否 | 传了 code_challenge 时默认 S256 |
nonce | 否 | 写入 id_token |
width / height | 否 | iframe 尺寸,默认 300 / 400 |
base | 否 | Kango 服务地址,默认从 kglogin.js 自身的地址推出(…/jssdk/kglogin.js 之前的部分),一般不用传 |
不用 iframe,整页跳转
也可以直接把浏览器跳到出码页(对标微信 open.weixin.qq.com/connect/qrconnect),参数同上:
text
https://kg.citv.cc/jssdk/qrconnect.html?appid=YOUR_APP_KEY&redirect_uri=https%3A%2F%2Fyour-site.com%2Fkango%2Fcallback&scope=openid%20profile&state=xxx第 2 步:回调页拿 code
用户确认后,浏览器跳到:
text
https://your-site.com/kango/callback?code=授权码&state=原样返回先比对 state 与会话里存的值,不一致直接拒绝。用户在手机上点「取消」不会回跳,二维码区域提示已取消,可刷新重扫。
第 3 步:服务端用 code 换 token、拉用户信息
与令牌端点、UserInfo 端点完全相同。机密客户端未传 code_challenge 时,换 token 不需要 code_verifier,凭 client_secret 即可(同微信「code + appid + secret」):
bash
# 换 token(在你的服务端执行,client_secret 不能出现在前端)
curl -X POST https://kg.citv.cc/api/oauth/token \
-d grant_type=authorization_code \
-d code=授权码 \
-d redirect_uri=https://your-site.com/kango/callback \
-d client_id=YOUR_APP_KEY \
-d client_secret=YOUR_APP_SECRET
# 拉用户信息
curl https://kg.citv.cc/api/oauth/userinfo \
-H "Authorization: Bearer ACCESS_TOKEN"拿到 sub(openId)后,在你的系统里查找或创建对应账号,建立自己的登录态(完整写法见 服务端完整示例)。同一开发者名下有多个应用需要识别同一用户时,申请 unionid scope,用 unionId 关联。
与微信网站应用登录的对照
| 微信 | Kango |
|---|---|
wxLogin.js / new WxLogin({...}) | kglogin.js / new KgLogin({...}) |
appid | appid(H5APP 的 AppKey) |
scope=snsapi_login | scope=openid profile(snsapi_login 也认) |
/sns/oauth2/access_token(GET) | /api/oauth/token(POST 表单) |
/sns/userinfo(access_token 放 query) | /api/oauth/userinfo(Bearer 头) |
openid / unionid / nickname / headimgurl | sub / unionId / nickname / picture |
| 开放平台登记「授权回调域」 | 开发者中心登记 redirect_uris 或网站域名 |
出码错误
appid 不存在或应用未上线、redirect_uri 未登记、公开客户端未传 code_challenge 等错误直接显示在二维码区域,不会回跳 redirect_uri。换 token / 拉用户信息的错误码见 错误响应。
安全提示
state必须由服务端生成、绑定用户会话并在回调时校验,否则攻击者可以把他自己的 code 塞给你的用户(登录 CSRF)。client_secret只能放服务端;纯前端应用请登记为公开客户端(AppType=1),并改用 PKCE。- 扫码登录挡不住「攻击者在自己电脑上打开你的登录页,把二维码发给受害者扫」。Kango App 确认页会醒目展示网站名称、申请的权限和请求来源 IP,请保证应用名称能让用户一眼认出是你的网站。
- 若你自己给 iframe 设置了
sandbox,须包含allow-scripts allow-same-origin allow-top-navigation,否则确认后无法自动跳转(出码页会退化为显示「点此继续」链接)。