网页手机号抓取程序(小程序登录和获取微信用户身份标识的加密数据说明)
优采云 发布时间: 2021-12-15 12:41网页手机号抓取程序(小程序登录和获取微信用户身份标识的加密数据说明)
小程序登录:
小程序可以通过微信官方提供的登录方式轻松获取到微信提供的用户身份,然后开发者就可以进行下一步了。
登录流程:
1、 调用wx.login()接口获取临时登录凭证码(用户登录凭证,有效期5分钟,该码只能使用一次,使用一次即失效)。
2、 服务端获取code,调用auth.code2Session接口获取用户唯一标识openId、用户在开放平台的唯一标识unionid、会话密钥session_key。
其中,会话密钥 session_key 是对用户数据进行加密和签名的密钥。为了应用程序自身的数据安全,开发者服务器不应将会话密钥分发给小程序,也不应将此密钥提供给外界。
3、服务器可以通过openId和session_key来自定义判断用户的登录状态。
获取用户信息
1、 用户授权后,小程序通过请求auth.code2Session()接口从接口返回的内容中获取用户信息,并对敏感信息进行加密。
auth.code2Session() 接口请求地址:
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
请求参数:
属性
类型
必需的
操作说明
应用程序
细绳
是的
小程序应用程序 ID
秘密
细绳
是的
小程序应用秘密
js_code
细绳
是的
登录时获取的代码
授权类型
细绳
是的
授权类型,这里填写authorization_code
小程序appId和小程序appSecret是在小程序管理平台上获取的,不会改变,可以写在配置文件中。
返回的json数据包:
属性
类型
操作说明
打开id
细绳
唯一用户 ID
会话密钥
细绳
会话密钥
工会号
细绳
满足UnionID发行条件,将返回用户在开放平台上的唯一标识。具体请参考UnionID机制说明。
错误码
细绳
错误代码
错误消息
细绳
错误信息
返回的加密信息参数说明:
范围
类型
操作说明
加密数据
细绳
包括敏感数据在内的完整用户信息的加密数据,详见
四
细绳
加密算法的初始向量,详见
云ID
细绳
敏感数据对应的云ID只有在打开云开发的小程序时才会返回,通过云调用可以直接获取打开的数据
2、 将加密信息传递给服务器,并使用登录时获取的session_key和appId对数据进行解密(将加密信息参数encryptedData和iv,以及登录时获取的session_key和appId传入WXBizDataCrypt.py程序解密)获取用户相关信息,包括微信姓名、性别、头像等,解密方式可查看微信开放数据校验和解密文档。
Python3解密加密信息码
WXBizDataCrypt.py:
import base64
import json
from Crypto.Cipher import AES
class WXBizDataCrypt:
def __init__(self, appId, sessionKey):
self.appId = appId
self.sessionKey = sessionKey
def decrypt(self, encryptedData, iv):
# base64 decode
sessionKey = base64.b64decode(self.sessionKey)
encryptedData = base64.b64decode(encryptedData)
iv = base64.b64decode(iv)
cipher = AES.new(sessionKey, AES.MODE_CBC, iv)
decrypted = json.loads(self._unpad(cipher.decrypt(encryptedData)))
if decrypted['watermark']['appid'] != self.appId:
raise Exception('Invalid Buffer')
return decrypted
def _unpad(self, s):
return s[:-ord(s[len(s)-1:])]
获取用户信息的代码如下:
# 解密获取用户信息
def decrypt_encrypteddata(self,session_key,encryptedData,iv):
decrypt_data = WXBizDataCrypt(APPID, session_key)
decrypt_data = decrypt_data.decrypt(encryptedData, iv)
return decrypt_data
# 登录接口
def get_VistorInfo(self, request_data):
"""
通过参数APPID, SECRET, js_code获取到用户的微信唯一标识openID和sessionKey
通过参数encryptedData 、iv 、sessionKey 请求后台解密获取用户信息
:param request_data: 请求参数包含encryptedData,iv,code
:return:
"""
try:
database = DataBase()
encryptedData = request_data.get('encryptedData')
iv = request_data.get('iv')
url_code2Session = "https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}" \
"&grant_type=authorization_code".format(APPID, SECRET, request_data.get('code'))
data = requests.get(url_code2Session)
if data.status_code == 200:
data_content = json.loads(data.content)
if 'session_key' in data_content:
session_key = data_content['session_key']
user_info = self.decrypt_encrypteddata(session_key, encryptedData, iv)
open_id = user_info.get('openId') # 微信用户唯一标识
session['open_id'] = open_id #将微信唯一标识open_id存在session中
session['session_key'] = session_key #将session_key存在session中
#这里是自己的逻辑实现,例如将用户信息存储到数据库中
#这里是自己的逻辑实现,例如将用户信息存储到数据库中
#这里是自己的逻辑实现,例如将用户信息存储到数据库中
res = {'code': 1, 'message': '用户已登录'}
else:
res = {'code': 2, 'message': '用户未登录'}
else:
res = {'code': 2, 'message': '用户未登录'}
return res
except Exception as e:
error_info = '用户登录失败:{}'.format(e)
logger.error(error_info)
finally:
database.closeConn()
加密数据解密算法 微信官方提供多种编程语言的示例代码
解密后返回数据的json格式如下:
{
"openId": "OPENID",
"nickName": "NICKNAME",
"gender": GENDER,
"city": "CITY",
"province": "PROVINCE",
"country": "COUNTRY",
"avatarUrl": "AVATARURL",
"unionId": "UNIONID",
"watermark":
{
"appid":"APPID",
"timestamp":TIMESTAMP
}
}
其中 avatarUrl 是头像的链接。
调试时返回的数据:
此外,从返回的数据中可以得到用户的微信昵称、性别、城市、微信头像。
会话密钥 session_key 有效性:
如果开发者遇到由于 session_key 错误导致签名验证或解密失败,请注意以下 session_key 相关的注意事项。
调用wx.login时,可能会更新用户的session_key,使旧的session_key失效(刷新机制周期最短。如果同一用户短时间内多次调用wx.login,不是每次调用都会导致session_key 被刷新)。开发者只有在明确需要重新登录时才调用wx.login,并及时通过auth.code2Session接口更新服务器中存储的session_key。session_key的有效期微信不会通知开发者。我们将根据用户使用小程序的行为更新 session_key。用户使用小程序越频繁,session_key 的有效期就越长。当 session_key 失效时,开发者可以通过重新执行登录过程来获取有效的 session_key。使用接口 wx。checkSession 来验证 session_key 是否有效,避免小程序重复执行登录过程。开发者在实现自定义登录状态时,可以将 session_key 的有效期视为自己登录状态的有效期,也可以实现自定义时效策略。
获取用户的手机号码
获取用户手机号与获取用户信息大致相同
需要用户主动触发才能发起手机号获取接口,所以这个函数不是API调用的,需要通过点击前端组件来触发。您可以查看和获取手机号码文档。
1、 小程序通过点击触发getPhoneNum事件,当用户点击同意时,获取加密信息;
代码示例:
Page({
getPhoneNumber (e) {
console.log(e.detail.errMsg)
console.log(e.detail.iv)
console.log(e.detail.encryptedData)
}
})
返回的加密信息:
范围
类型
操作说明
加密数据
细绳
包括敏感数据在内的完整用户信息的加密数据,详见
四
细绳
加密算法的初始向量,详见
云ID
细绳
敏感数据对应的云ID只有在打开云开发的小程序时才会返回,通过云调用可以直接获取打开的数据
2、 将加密后的信息发送到服务器,使用登录时获取的session_key和appId对数据进行解密,获取微信用户绑定的手机号。
将加密信息参数encryptedData和iv,以及登录时获取的session_key和appId,传入WXBizDataCrypt.py程序进行解密。
解密后返回数据的json结构如下:
{
"phoneNumber": "13580006666",
"purePhoneNumber": "13580006666",
"countryCode": "86",
"watermark":
{
"appid":"APPID",
"timestamp": TIMESTAMP
}
}
其中,phoneNumber为用户绑定的手机号码(国外手机号码有区号);purePhoneNumber 是没有区号的手机号码;countryCode 是区号。
此外,从返回的数据中,可以得到用户微信绑定的手机号码。
获取手机号码的代码如下:
# 获取用户手机号
def get_phone(self, request_data):
"""
通过参数encryptedData 、iv 、sessionKey 请求后台解密获取用户手机号
:param request_data:
:return:
"""
try:
database = DataBase()
if 'session_key' in session and session['session_key']:
session_key = session['session_key']
open_id = session['open_id']
phone_info = self.decrypt_encrypteddata(session_key, request_data.get('encryptedData'), request_data.get('iv'))
phone_number = phone_info.get('phoneNumber')
sql = """ """
database.insertSql(sql)
res = {'code': 1, 'message': '操作完成'}
return res
else:
res = {'code': 2, 'message': '用户未登录'}
return res
except Exception as e:
error_info = '获取手机号出错:{}'.format(e)
logger.error(error_info)
finally:
database.closeConn()
注意:
在回调中调用 wx.login 登录可能会刷新登录状态。这时服务器使用code交换的sessionKey并不是加密时使用的sessionKey,导致解密失败。建议开发者提前登录;或者在回调中使用checkSession检查登录状态,防止登录刷新登录状态。
总结流程:首先通过请求参数APPID、SECRET、js_code获取用户的微信唯一标识openID和sessionKey;然后使用参数encryptedData、iv、sessionKey请求后台接口解密用户信息;最后,从返回的json数据或Phone number中提取用户信息。
参考: