uni-id 是 uniapp 自带的一套用户用户体系,按照官方文档的说法,具有颇多优势。目前闺蜜圈项目是自建用户体系,但是为了后续的功能规划,可能需要用到 uni-id 的账号体系,所以提前进行了相关可行性测试。
99%的应用,都要开发用户注册、登录、发送短信验证码、修改密码、密码加密保存、密码防探测、token管理、页面访问权限、注册用户统计等众多功能,从前端到后端都需要。
为什么不能有一个开源的通用项目,避免大家的重复开发呢?
uni-id应需而生。
uni-id为uniCloud开发者提供了开源、易用、安全、丰富、可扩展的用户管理框架。clientDB、DB Schema、uni-starter、uni-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以及对应的字段。
											
8 comments
这个看不懂。
Mark一下慢慢体会。
来看看,这样就不用重复造轮子了,那用户数据是存在他们云端还是自己服务器呀
目前数据都在自己的服务器上,他们这个是准备做其他的一些功能。暂时还没确定做还是不错。
除了大姨妈,又是别外一个项目?真有精力
还是那个 在完善相关能力
我也表示看不懂,哈哈哈😄😄😄😄
no matters