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