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