developers, tutorial,

Authing 移动端登录方式, 10 行代码实现 App 扫码登录

廖长江 廖长江 Follow Mar 01, 2020 · 6 mins read
Authing 移动端登录方式, 10 行代码实现 App 扫码登录
分享

Authing 新增四种移动端登录方式:移动应用微信登录、移动应用支付宝登录、App 拉起小程序登录、App 扫码登录。

Authing 新增了对四种移动端登录方式的支持,可以让开发者在 Web 端、移动端、小程序端同时接入 Authing:

  • 移动应用微信登录
  • 移动应用支付宝登录
  • App 拉起小程序登录
  • App 扫码登录

点击上图跳转到 GitHub Demo 页面。

其中,「App 拉起小程序登录」指的是在 App 中,借助微信开放能力,唤起微信小程序「小登录」,获取用户微信授权进行登录。此方法可以获取到用户手机号。

下面分别介绍一下如何快速接入这四种登录方式。

App 拉起小程序登录

接入 App 拉起小程序登录,你需要做如下准备工作:

  • 非私有化部署用户,需要将你的移动应用关联小登录。

可在微信开放平台 “管理中心-移动应用-应用详情-关联小程序信息”,为通过审核的移动应用发起关联小程序操作。小登录的 AppID 为 wxa0435021fd7a3af2 .

在你做好这些准备工作之后,先使用微信 SDK 拉起小程序(具体的接入流程请见微信官方文档):

  • 小程序 userName 为 gh_a781a791e29e
  • path 为 /routers/explore
  • path query 参数为:
    • userPoolId: 你的用户池 ID
    • getPhone: 是否需要获取用户手机号,1 表示需要,不填或者其他表示不需要
    • fromApp: 1,此参数必填。
    • useSelfWxapp: 此参数必填。私有化用户填 1,非私有化用户填 0.

下面是 Swift 代码示例:

let userPoolId = "5e4cdd055df3df65dc58b97d"
let req = WXLaunchMiniProgramReq()
req.userName = "gh_a781a791e29e"
req.path = "/routes/explore?userPoolId=\(userPoolId)&getPhone=1&fromApp=1&useSelfWxapp=0"
req.miniProgramType = WXMiniProgramType.release
WXApi.send(req)

用户同意授权之后,会携带 ticket 跳回你的 App,之后你可以使用此 ticket 换取用户信息:

POST https://oauth.authing.cn/oauth/app2wxapp/auth/:userPoolId

  • Path 参数 userPoolId: 你的 Authing 用户池 ID。
  • Post Body 参数:
    • ticket: 得到的 ticket
    • secret: 用户池密钥。默认情况下,出于安全考虑,ticket 换取用户信息需要提供用户池密钥,这意味着不能直接在 App 内直接换取用户信息。开发者可以在用户池基础配置页面修改此选项:

下面是演示示例:

此方式可以获取用户手机号。你可以扫描下方的小程序二维码体验一下「小登录」:

如果你想私有化部署自己的小程序,可以联系我们。手机号:18616699123。

详细接入流程请见:接入APP 拉起小程序登录

App 扫码登录

和其他三种登录方式不同,你不需要做任何准备工作。同时,我们提供 Web 端的 SDK,可以让你在 Web 端使用 10 行代码实现一个完整的扫码登录表单:

const Authing = require('authing-js-sdk');

// 初始化 Authing SDK for JavaScript
const authing = new Authing({
    userPoolId: 'YOUR_USERPOOL_ID',
});

// 调用 APP 扫码登录的方法,此方法将生成一个用于扫码登录的图片和相关提示信息
authing.qrlogin.startScanning({
  onSuccess(data) {
    console.log(data);
    const {ticket, userInfo} = data;
    // 存储 token 到 localStorage 中
    localStorage.setItem('token', userInfo.token);
  }
})

That’s it! 就这么简单!

下面是 startScanning 支持的完整参数,你可以掌控扫码登录的所有流程,实现高度自定义:

authing.qrlogin.startScanning({
    mount: '', // 可选,二维码挂载点,如不写则默认漂浮在文档中间
    interval: 1000, // 可选,轮询间隔时间,默认为 800 ms 

    onPollingStart: (intervalNum) => {},
    onResult: (res) => {},
    onScanned: (userInfo) => {},
    onSuccess: (data) => {
        const { ticket, userInfo } = data;
    },
    onCancel: () => {},
    onExpired: () => {},
    onError: (data) => {},

    onQRCodeShow: (qrcode) => {},
    onQRCodeLoad: (qrcode) => {},
    onQRCodeLoadFaild: (error) => {},
    
    tips: '使用 <strong> APP </strong> 扫码登录',
    scannedTips: '用户已扫码,等待确认',
    canceledTips: '用户取消授权',
    expiredTips: '二维码已过期',
    successTips: '扫码成功',
    retryTips: '重试',
    failedTips: '网络出错,请重试'
})
参数 可选/必选 说明
mount 可选 挂载点 Dom ID,如不写则默认漂浮在文档中间。
interval 可选 轮询时间间隔,单位为 ms,默认为 800 ms。
onPollingStart 可选 轮询开始时会被回调,只会回调一次。回调参数 intervalNum 为 setInterval 返回的数值,可使用 clearInterval 停止轮询。如:clearInterval(intervalNum)
onResult 可选 每次查询获取到数据都会回调
onScanned 可选 用户扫码时会被回调,只会回调一次。回调参数 userInfo 只包含了用户昵称和头像,开发者可以将其展示在扫码框中。
onSuccess 可选 用户同意授权之后将会被回调,只会回调一次,之后轮询结束。参数 data 是一个字典,包含两个字段:ticket 和 userInfo。出于安全性考虑,默认情况下,userInfo 只会包含昵称(nickname)和头像(photo)两个字段,开发者也可以在后台配置使其返回完整用户信息,详情见自定义配置。 ticket 可以用来换取完整的用户信息,相关接口见下文。
onCancel 可选 用户取消授权只会会被回调,只回调一次,之后轮询结束。
onExpired 可选 二维码失效时被回调,只回调一次,之后轮询结束。
onError 可选 每次查询失败时都会回调。回调参数 data 示例如 {“code”: 2241,”message”: “二维码不存在”,”data”: null}。完整错误代码请见完整错误代码页。
onQRCodeLoad 可选 二维码首次成功加载时回调。回调参数 qrcode 是一个字典,包含两个字段:qrcodeId、qrcodeUrl。
onQRCodeShow 可选 二维码首次出现在页面上时回调。回调参数 qrcode 同上。
onQRCodeLoadFaild 可选 二维码加载失败时会被回调。

在移动端,开发者可以调用 iOS/Android 相关接口解析二维码,二维码包含原始数据如下:

{
    "scene": "APP_AUTH",
    "qrcodeId": "5e05f0c57fde537d950f7da5",
    "userPoolId": "5e04ae0d5f3cee22fb37612b",
    "createdAt": "2019-12-27T11:53:41.260Z",
    "expireAt": "2019-12-27T11:55:41.260Z",
    "userDefinedData": { "hello": "world" }
}
  • scene: 二维码场景值,APP_AUTH 表示 APP 扫码登录。
  • qrcodeId: 二维码 ID。
  • qrcodeId: 用户池 ID。
  • userDefinedData: 用户自定义数据。

接着可以调用 Authing API,进行标记已扫码、同意授权、取消授权操作,如同意授权的 API 如下:

POST https://oauth.authing.cn/oauth/scan-qrcode/confirm

  • 请求头 Authorization: 已登录用户的 token
  • Body 参数 qrcodeId: 二维码 ID。

以下是一个对应的 Swift 代码示例:

import Alamofire

func confirmQRLogin(qrcodeId: String) {
    let api = "https://oauth.authing.cn/oauth/scan-qrcode/confirm"
    let headers: HTTPHeaders = [
        "Authorization": "<USER_TOKEN>",
        "Accept": "application/json"
    ]
    struct Body: Encodable {
        let qrcodeId: String
    }
    let body = Body(qrcodeId: qrcodeId)
    AF.request(
        api,
        method: .post,
        parameters: body,
        headers: headers
    ).responseString { response in
        
        // 将 response.value 转化成字符串,示例如下:
        // ["code": 200, "message": "二维码扫描确认成功", data: "" ]
        let resp = convertToDictionary(text: response.value!)!
        let code = resp["code"] as! Int
        if code != 200 {
            debugPrint("确认授权失败: ", resp)
        }
    }
}

详细接入方式请见:接入 App 扫码登录

微信登录与支付宝登录

接入移动应用微信登录和支付宝登录,你需要做如下准备工作:

  • 注册 Authing 开发者账号
  • 申请微信、支付宝移动应用
  • 在 Authing 控制台填入微信、支付宝移动应用信息
  • 接入微信、支付宝移动端 SDK

在你做好这些准备工作之后,先使用微信/支付宝 SDK 拉起微信/支付宝,用户同意授权之后,你会得到一个 code。此 code 可通过 Authing 的接口换取用户信息。

以微信登录 API 为例:

GET https://oauth.authing.cn/oauth/wechatmobile/auth/:userPoolId?code=<YOUR_CODE>

  • path 参数 userPoolId: 你的用户池 ID。
  • query 参数 code: 拉起微信得到的 code。

下面是 Swift 示例代码:

import Alamofire

let url = "https://oauth.authing.cn/oauth/wechatmobile/auth/\(UserPoolId)?code=\(code!)"
AF.request(url).responseString { response in
    debugPrint("Response: \(response.value)")
}

详细的接入流程请见:

获取用户信息之后

获取到用户信息之后,你可以得到登录凭证 token,你可以在后续的 API 请求中携带上此 token, 然后在后端接口中根据此 token 区分不同用户。

设置 Authorization 请求头为 “Bearer “ + token, 例如:

Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InVuaW9uaWQiOiJvaVBiRHVHNFM3bXNyS0hQS0RjOE1FQ1NlOGpNIiwiaWQiOiI1ZGMxMGJjYjZmOTRjMTc4YzZmZmZmYjkiLCJjbGllbnRJZCI6IjVkYTdlZGFiNTAzOTZjMWFkOTYyMzc4YSJ9LCJpYXQiOjE1NzI5NTY0MjUsImV4cCI6MTU3NDI1MjQyNX0.OTgl72WZS8So3R5DbWCJ7I_Bd0LaZa4S0TAVMg9qaYQ"

如果你使用的是 Swift 的 Alamofire, 可以这样写:

let api = "YOUR_SERVICE_URL"
let headers: HTTPHeaders = [
    "Authorization": "<USER_TOKEN>",
    "Accept": "application/json"
]
let body = Body(qrcodeId: qrcodeId)
AF.request(
    api,
    method: .post,
    headers: headers
).responseString { response in
  print(response.value)
}

你可以在后端调用 Authing 的 API 验证通过 Authorization 判断该用户是否具备相关权限。

详情请见验证 token

总结

你可以在这个 GitHub 项目找到完整的示例代码:https://github.com/Authing/AuthingIOSDemo

以下是 Authing 目前支持的社会化登录方式,国内主流的第三方身份提供商目前都已经支持了:

同时我们接下来会继续不断完善,让有身份认证的地方就有 Authing !

廖长江
Written by 廖长江 Follow
Web fullstack developer.