Uni-id-co 外部系统联登

uni-id 是 uniapp 自带的一套用户用户体系,按照官方文档的说法,具有颇多优势。目前闺蜜圈项目是自建用户体系,但是为了后续的功能规划,可能需要用到 uni-id 的账号体系,所以提前进行了相关可行性测试。

99%的应用,都要开发用户注册、登录、发送短信验证码、修改密码、密码加密保存、密码防探测、token管理、页面访问权限、注册用户统计等众多功能,从前端到后端都需要。

为什么不能有一个开源的通用项目,避免大家的重复开发呢?

uni-id应需而生。

uni-iduniCloud开发者提供了开源、易用、安全、丰富、可扩展的用户管理框架。

clientDBDB Schemauni-starteruni-admin,这些产品都基于uni-id的账户体系。可以说uni-id是uniCloud不可或缺的基础能力。

同时针对已经有账号体系的系统提供了接口,实现数据互通:https://doc.dcloud.net.cn/uniCloud/uni-id/cloud-object.html#external-register

本身就提供了三个接口,没有查询用户信息的功能,按照官网文档实现数据对接也比较容易,不过需要注意的是,文档里面有些内容没有写清楚。

校验算法代码:

import hmac
import hashlib
import time

# https://doc.dcloud.net.cn/uniCloud/uni-id/cloud-object.html#http-reqeust-auth
class Sign:
    def __init__(self, requestAuthSecret):
        self.requestAuthSecret = requestAuthSecret

    def get_signature(self, params, nonce, timestamp):
        params_str = self.get_params_string(params)
        signature = hmac.new(bytes("%s%s" % (self.requestAuthSecret, nonce), 'utf-8'),
                             bytes("%s%s" % (timestamp, params_str), 'utf-8'),
                             digestmod=hashlib.sha256).hexdigest().upper()

        return signature

    def get_params_string(self, params):
        params_str = []
        for k in sorted(params):
            if isinstance(params[k], (list, dict)):
                continue
            params_str.append("%s=%s" % (k, params[k]))

        return "&".join(params_str)


if __name__ == "__main__":
    requestAuthSecret = "testSecret"
    nonce = "xxxxxxx"
    timestamp = int(round(time.time() * 1000))

    params = {
        "foo": 1,
        "bar": 2,
        "foobar": 4,
        "foo_bar": 3,
    }

    sign = Sign(requestAuthSecret)
    signature = sign.get_signature(params, nonce, timestamp)

    print(nonce, timestamp, signature)

对应三个接口的代码封装:

import datetime
import json
import random
import string
import requests
import asyncio
import traceback
import time

from reminder.utils.string_util import random_str
from reminder.utils.uni_sign import Sign as UniSign

requestAuthSecret = 'mysecret' #需要去uniadmin配置文件中设置
sign = UniSign(requestAuthSecret)

# https://doc.dcloud.net.cn/uniCloud/uni-id/cloud-object.html#external-register
'''
uni-id-nonce	string	是	随机字符串
uni-id-timestamp	string	是	当前时间戳; 单位毫秒
uni-id-signature	string	是	请求鉴权签名; 签名算法见下
POST /your-uni-id-co-path/externalRegister HTTP/1.1
Host: xxx.com
uni-id-nonce: xxxxxxx
uni-id-timestamp: 1676882808550
uni-id-signature: 11c965267a4a02c6978949c7135215b0a75aea22b2b84ed491e792365c8269efa
Content-Type: application/json
Cache-Control: no-cache

{"externalUid": "test externalUid", "nickname": "张三", "avatar": "xxxxxxx", "gender": 0}
externalUid	string	是	自身系统的用户id,必须保证唯一性。
nickname	string	否	用户昵称
avatar	string	否	用户头像
gender	number	否	用户性别;0 未知 1 男性 2 女性
'''


def external_register(external_uid, nickname, avatar, gender):
    body = {
        'externalUid': str(external_uid),
        'nickname': nickname,
        # 'avatar':'',
        # 'gender':''
    }
    timestamp = int(round(time.time() * 1000))
    nonce = random_str(16)
    headers = {
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache',
        'uni-id-nonce': nonce,
        'uni-id-timestamp': str(timestamp),
        'uni-id-signature': sign.get_signature(body, nonce, timestamp)
    }
    print(body)

    req_body = {
        "clientInfo": {'uniPlatform': 'app',
                       'appId': '__UNI__*******'},
        "params": body
    }

    resp = requests.post("https://c******/uni-id-co/externalRegister", json=req_body, headers=headers) # 需要将云函数url化
    print('Reg Resp:', resp.text)
    return resp.text


'''
参数名	类型	必填	说明
uid	string	否	uni-id体系的用户Id;与externalUid 二选一
externalUid	string	否	自身系统的用户id;与 uid 二选一
'''


def external_login(uid, external_uid):
    body = {
        # 'uid':str(uid),
        'externalUid': str(external_uid),
        # 'nickname': nickname,
        # 'avatar':'',
        # 'gender':''
    }
    timestamp = int(round(time.time() * 1000))
    nonce = random_str(16)
    headers = {
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache',
        'uni-id-nonce': nonce,
        'uni-id-timestamp': str(timestamp),
        'uni-id-signature': sign.get_signature(body, nonce, timestamp)
    }
    print(body)

    req_body = {
        "clientInfo": {'uniPlatform': 'app',
                       'appId': '__UNI__E*******'},
        "params": body
    }

    resp = requests.post("https://c*******/uni-id-co/externalLogin", json=req_body, headers=headers)
    print('Reg Resp:', resp.text)
    return resp.text


'''
uid	string	否	uni-id体系的用户Id;与externalUid 二选一
externalUid	string	否	自身系统的用户id;与 uid 二选一
username	string	否	用户名
password	string	否	密码
nickname	string	否	昵称
authorizedApp	Array<string>	否	允许登录的app列表
role	Array<string>	否	用户角色
mobile	string	否	手机号
email	string	否	邮箱
tags	array	否	用户标签
status	number	否	用户状态,参考:用户状态
avatar	string	否	用户头像
gender	number	否	用户性别;0 未知 1 男性 2 女性
'''
def external_update(uid, external_uid, username, password, nickname, mobile, email, status,
                    avatar, gender):
    body = {
        # 'uid':str(uid),
        'externalUid': str(external_uid),
        # # 'nickname': nickname,
        # # 'avatar':'',
        # # 'gender':''
        # 'username': username,
        # 'password': password,
        # 'nickname': nickname,
        # # 'authorizedApp': authorizedApp,
        # # 'role': role,
        # 'mobile': mobile,
        # 'email': email,
        # # 'tags': tags,
        # 'status': status,
        # 'avatar': avatar,
        # 'gender': gender,
    }
    if username and username != '':
        body['username'] = username
    if nickname and nickname != '':
        body['nickname'] = nickname
    if password and password != '':
        body['password'] = password
    if mobile and mobile != '':
        body['mobile'] = mobile
    if email and email != '':
        body['email'] = email
    if status and status != '':
        body['status'] = status
    if avatar and avatar != '':
        body['avatar'] = avatar
    if gender and gender != '':
        body['gender'] = gender

    timestamp = int(round(time.time() * 1000))
    nonce = random_str(16)
    headers = {
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache',
        'uni-id-nonce': nonce,
        'uni-id-timestamp': str(timestamp),
        'uni-id-signature': sign.get_signature(body, nonce, timestamp)
    }
    print(body)

    req_body = {
        "clientInfo": {'uniPlatform': 'app',
                       'appId': '__UNI__E*******'},
        "params": body
    }

    resp = requests.post("https://c*******/uni-id-co/updateUserInfoByExternal", json=req_body, headers=headers)
    print('Reg Resp:', resp.text)
    return resp.text



if __name__ == "__main__":
    print('uni rest request')
    # external_register('17', 'test', '', '')
    # external_login('', '17')
    # external_update('', '17','test','','','','','','', '')

post body需要是下面的格式:

req_body = {
    "clientInfo": {'uniPlatform': 'app',
                   'appId': '__UNI__E8*******'},
    "params": body
}

上述内容在文档中没有说明,需要自己添加clientInfo以及对应的字段。

 

☆版权☆

* 网站名称:obaby@mars
* 网址:https://obaby.org.cn/
* 个性:https://oba.by/
* 本文标题: 《Uni-id-co 外部系统联登》
* 本文链接:https://obaby.org.cn/2024/03/15787
* 短链接:https://oba.by/?p=15787
* 转载文章请标明文章来源,原文标题以及原文链接。请遵从 《署名-非商业性使用-相同方式共享 2.5 中国大陆 (CC BY-NC-SA 2.5 CN) 》许可协议。


You may also like

8 comments

  1.  Level 5
    Google Chrome 86 Google Chrome 86 Windows 10 Windows 10 cn中国–广东–珠海 电信

    来看看,这样就不用重复造轮子了,那用户数据是存在他们云端还是自己服务器呀

    1. 公主 Queen 
      Google Chrome 118 Google Chrome 118 Mac OS X 10.15 Mac OS X 10.15 cn中国–山东–青岛 联通

      目前数据都在自己的服务器上,他们这个是准备做其他的一些功能。暂时还没确定做还是不错。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注