ps:
Q群:743496144
博主一向不喜欢废话,直接说几个点,你悟了就直接去试,可以不用看完,还是得自己去试印象才深刻,博主写博文就怕自己以后忘记做个笔记顺便能帮一个是一个
1、你要获取unionid 肯定得访问外网,uniCould的访问外网api是uniCloud.httpclient.request,用法可以点后面这个api->简介@intro | uni-app官网,然后对接的微信官方获取unionid 的是这个地址小程序登录 | 微信开放文档
2、uniCloud.httpclient.request 是放云对象里面,到时候你在同步到云端到云对象就可以
3、涉及signature对比验证(sha1加密算法)
4、涉及AES算法(存云对象的cryptojs,放心,不是让你cnpm install,你顺便还知道下怎么把依赖存云对象里)
5、写完这篇博文博主没了半条命,uniCloud资料本来就少,你们全看完的,给我去点赞!
一、准备:
1、记下AppID(小程序ID)、AppSecret(小程序密钥),
顺便配置下云开发的地址(博主是申请阿里云的云开发5块钱的商用版的 所以配置这个,你要是免费到地址,你要开你微信开发工具请求云对象到时候的请求地址是啥配置进来就可以)
2、微信开放平台---》微信开放平台
绑定你的小程序,unionid 获取这一步逃不掉,个人也可以注册微信开发平台!!!!!!,当然如果你是公司项目,比如公众号和小程序都要知道是不是同一个用户登录,就得用公司的账号认证去开通微信开放平台
3、组件
pages/user/user.vue (你随便放一个page的vue文件里就好,记得你页面要配置路由,要访问到了)
pages.json要配置这个 pages/user/user.vue
<template>
<view>
<button class="loginBtn" open-type="getUserInfo" @getuserinfo="wxGetUserInfo">授权登陆</button>
</view>
</template>
<script>
export default {
data() {
return {
}
},
computed: {
},
mounted(){
let m=this;
},
methods: {
wxGetUserInfo() {
let m = this;
m.tologin("weixin");
},
tologin(provider) {
let m=this;
uni.login({
provider: provider,
// #ifdef MP-ALIPAY
scopes: 'auth_user', //支付宝小程序需设置授权类型
// #endif
success: (res) => {
m.loginVal=res;
m.getUserInfo((res1)=>{
let params={
"code": m.loginVal.code,
"rawData": res1.rawData,
"nickName": res1.userInfo.nickName,
"gender":res1.userInfo.gender,
"avatarUrl": res1.userInfo.avatarUrl,
"signature":res1.signature,
"encryptedData": res1.encryptedData,
"iv": res1.iv,
"language": res1.userInfo.language,
"city":res1.userInfo.city,
"province": res1.userInfo.province,
"country": res1.userInfo.country,
}
m.apiJscode2session(params)
})
},
fail: (err) => {
}
});
},
async apiJscode2session(params){
const co1 = uniCloud.importObject("col");
let res=await co1.wxjscode2session(params);
debugger
},
getUserInfo(suc) {
suc=suc||function(){}
uni.getUserInfo({
provider: "weixin",
success: (result) => {
suc(result);
},
})
// uni.getUserInfo({
// provider: "weixin",
// success: (result) => {
// suc(result);
// },
// fail: (error) => {
// }
// });
},
}
}
</script>
<style>
</style>
co1.wxjscode2session的云对象目录结构如下图
index.obj.js 代码
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
module.exports = {
_before: function () { // 通用预处理器
},
say(str){
return{
code:"200",
data:str
}
},
async wxjscode2session(params){
let m=this;
let url="https://api.weixin.qq.com/sns/jscode2session?appid=你的AppID(小程序ID)&secret=你的AppSecret(小程序密钥)&js_code="+params.code+"&grant_type=authorization_code"
const res = await uniCloud.httpclient.request(url, {
method: 'GET',
dataType: 'json' // 此处指定为json表示将此请求的返回值解析为json
})
debugger
// https://api.weixin.qq.com/sns/jscode2session
},
/**
* method1方法描述
* @param {string} param1 参数1描述
* @returns {object} 返回值描述
*/
/*
method1(param1) {
// 参数校验,如无参数则不需要
if (!param1) {
return {
errCode: 'PARAM_IS_NULL',
errMsg: '参数不能为空'
}
}
// 业务逻辑
// 返回结果
return {
param1 //请根据实际需要返回值
}
}
*/
}
package.json
{
"name": "col",
"dependencies": {},
"extensions": {
"uni-cloud-jql": {}
}
}
对了这里要配置
好了,记得改完保存代码
接下去运行到小程序的时候,uniCloud控制台 开启断点调试,你可以还是连接本地云函数,毕竟我们本地开发,到时候记得同步到云端就好
点登陆,代码都给你们了,在上面那
点登陆,hBuilder X 会一闪一闪
unionid 就出来了,
核验signature
好,我们接下核验signature1,服务器通过前端给的rawData 加获取的session_key使用sha1加密,计算出signature1
这部有必要,比对前端传的signature和自己算出来的signature1是否一致(防止数据不一致,有时候延迟啥的,怕你存错unionid给不痛用户)
我之前线上项目有碰到 第一个用户请求完了,第二个用户一起请求,结果返回第二个用户的信息(其实这也是防止别人抓包,拦截你的请求和返回给你假的用户数据来注册你的小程序)
1/在 云对象 cloudfunctions/col/index.obj.js 就是我上面那个给出的代码的module.exports = { 上面放两个函数
function encodeUTF8(s) {
var i, r = [],
c, x;
for (i = 0; i < s.length; i++)
if ((c = s.charCodeAt(i)) < 0x80) r.push(c);
else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x1F), 0x80 + (c & 0x3F));
else {
if ((x = c ^ 0xD800) >> 10 == 0) //对四字节UTF-16转换为Unicode
c = (x << 10) + (s.charCodeAt(++i) ^ 0xDC00) + 0x10000,
r.push(0xF0 + (c >> 18 & 0x7), 0x80 + (c >> 12 & 0x3F));
else r.push(0xE0 + (c >> 12 & 0xF));
r.push(0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
};
return r;
}
function sha1(s) {
let m1 = this;
var data = new Uint8Array(encodeUTF8(s))
var i, j, t;
var l = ((data.length + 8) >>> 6 << 4) + 16,
s = new Uint8Array(l << 2);
s.set(new Uint8Array(data.buffer)), s = new Uint32Array(s.buffer);
for (t = new DataView(s.buffer), i = 0; i < l; i++) s[i] = t.getUint32(i << 2);
s[data.length >> 2] |= 0x80 << (24 - (data.length & 3) * 8);
s[l - 1] = data.length << 3;
var w = [],
f = [
function() {
return m[1] & m[2] | ~m[1] & m[3];
},
function() {
return m[1] ^ m[2] ^ m[3];
},
function() {
return m[1] & m[2] | m[1] & m[3] | m[2] & m[3];
},
function() {
return m[1] ^ m[2] ^ m[3];
}
],
rol = function(n, c) {
return n << c | n >>> (32 - c);
},
k = [1518500249, 1859775393, -1894007588, -899497514],
m = [1732584193, -271733879, null, null, -1009589776];
m[2] = ~m[0], m[3] = ~m[1];
for (i = 0; i < s.length; i += 16) {
var o = m.slice(0);
for (j = 0; j < 80; j++)
w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1),
t = rol(m[0], 5) + f[j / 20 | 0]() + m[4] + w[j] + k[j / 20 | 0] | 0,
m[1] = rol(m[1], 30), m.pop(), m.unshift(t);
for (j = 0; j < 5; j++) m[j] = m[j] + o[j] | 0;
};
t = new DataView(new Uint32Array(m).buffer);
for (var i = 0; i < 5; i++) m[i] = t.getUint32(i << 2);
var hex = Array.prototype.map.call(new Uint8Array(new Uint32Array(m).buffer), function(e) {
return (e < 16 ? "0" : "") + e.toString(16);
}).join("");
return hex;
}
module.exports = {
_before: function() { // 通用预处理器
},
say(str) {
我就贴出部分代码你知道放哪里就好
然后wxjscode2session做改动
async wxjscode2session(params) {
let url="https://api.weixin.qq.com/sns/jscode2session?appid=你的AppID(小程序ID)&secret=你的AppSecret(小程序密钥)&js_code="+params.code+"&grant_type=authorization_code"
const res = await uniCloud.httpclient.request(url, {
method: 'GET',
dataType: 'json' // 此处指定为json表示将此请求的返回值解析为json
})
let unionid=res.data.unionid;
//服务器通过前端给的rawData 加获取的session_key使用sha1加密,计算出signature1
let signature1 = sha1(params.rawData + res.data.session_key);
//比对前端传的signature和自己算出来的signature1是否一致(防止数据不一致,有时候延迟啥的,怕你存错unionid给不同用户)
if(params.signature==signature1){//
return res;//这边你可以做存用户unionid的请求操作
}else{
return false;
}
// https://api.weixin.qq.com/sns/jscode2session
},
这一步你云函数调试下就摘掉对错了,这个叫sha1算法加密解密,我备注写的很详细了!!!!!!,参考了下面这篇文章步骤微信小程序登录 + 基于token的身份验证_每天开心成为别人的望尘莫及的博客-CSDN博客的流程步骤,我按着他的思路来实现的。
AES算法解密encryptedData
好,接下去来用AES算法解密encryptedData里的敏感数据,
这里你注意去看看公告,如果你通过解密encryptedData是行不通的,你看看公告小程序用户头像昵称获取规则调整公告 | 微信开放社区
但是如果你的版本库低于2.27.1版本的访问,还是可以!!!!!!!!小伙伴帮博主试过了2.26.2版本uni.getuserProfile是可以获取头像、昵称的。
在这里改的版本库!!!!
先让你们看看博主解密的结果博主2.30.0的版本库,这个是解密encryptedData之后的。
哎,考虑到低于2.27.1的小伙伴,雪狼还是写下操作步骤吧
解密encryptedData(大于2.27.1的小伙伴就不用试了,没意义)
用AES算法解密encryptedData里的敏感数据,
首先就得下AES算法公式,所以你得下CryptoJS依赖,
但是CryptoJS 在uniCloud里是没有utils这个目录放依赖的概念的,
更不可能让你cnpm生成个本地node_modules,
咋整???
你有两个办法你去cnpm install crypto-js 可以!!!!,但是你得移动目录,到你的云对象里,怎么移动?看下图,看懂了吗。
博主不是这么操作!!!,先是去下了个crypto-js依赖包,这里借鉴下面这个博主,贴个原文,表示尊重和感谢,使用CryptoJS解决微信小程序用户信息解密 - 蔡-Rd - 博客园
博主的做法,
1、先下个cryptojs 点击下载
2、在cloudfunctions下的col新建一个文件夹node_modules 上图那你也看的到博主的目录,就是把解压后的cryptojs-master 重命名成cryptojs
3、新建个RdWXBizDataCrypt.js,上图那也有放的目录
代码如下
/**
* Created by rd on 2017/5/4.
*/
// 引入CryptoJS
var Crypto = require('cryptojs/cryptojs.js').Crypto;
function RdWXBizDataCrypt(appId, sessionKey) {
this.appId = appId
this.sessionKey = sessionKey
}
RdWXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// base64 decode :使用 CryptoJS 中 Crypto.util.base64ToBytes()进行 base64解码
var encryptedData = Crypto.util.base64ToBytes(encryptedData)
var key = Crypto.util.base64ToBytes(this.sessionKey);
var iv = Crypto.util.base64ToBytes(iv);
// 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充
var mode = new Crypto.mode.CBC(Crypto.pad.pkcs7);
try {
// 解密
var bytes = Crypto.AES.decrypt(encryptedData, key, {
asBpytes:true,
iv: iv,
mode: mode
});
var decryptResult = JSON.parse(bytes);
} catch (err) {
console.log(err)
}
if (decryptResult.watermark.appid !== this.appId) {
console.log(err)
}
return decryptResult
}
module.exports = RdWXBizDataCrypt
然后index.obj.js文件改动部分
const WXBizDataCrypt = require('./RdWXBizDataCrypt.js');
module.exports = {
_before: function() { // 通用预处理器
},
say(str) {
return {
code: "200",
data: str
}
},
async wxjscode2session(params) {
let url="https://api.weixin.qq.com/sns/jscode2session?appid=你的AppID(小程序ID)&secret=你的AppSecret(小程序密钥)&js_code="+params.code+"&grant_type=authorization_code"
const res = await uniCloud.httpclient.request(url, {
method: 'GET',
dataType: 'json' // 此处指定为json表示将此请求的返回值解析为json
})
let unionid=res.data.unionid;
//服务器通过前端给的rawData 加获取的session_key使用sha1加密,计算出signature1
let signature1 = sha1(params.rawData + res.data.session_key);
//比对前端传的signature和自己算出来的signature1是否一致(防止数据不一致,有时候延迟啥的,怕你存错unionid给不痛用户)
var pc = new WXBizDataCrypt(你的AppID(小程序ID), res.data.session_key)
var data = pc.decryptData(params.encryptedData , params.iv)
debugger
if(params.signature==signature1){//
return res;//这边你可以做存用户unionid的请求操作
}else{
return false;
}
// https://api.weixin.qq.com/sns/jscode2session
},
这句别漏掉 !!! const WXBizDataCrypt = require('./RdWXBizDataCrypt.js');
这个debugger那边上面到 data 你云调试下,就是你要得东西了(大于2.27.1微信版本库的小伙伴就别再说怎么没有了,博主上面都说过了!!!)
低于2.27.1的小伙伴如果试有数据,回来评论区顺便跟博主说下
对了你试了可以记得云函数同步云端去!!!!!!!!
你都看到这里 了,继续看下面文字吧。
写这篇博文没了半条命,毕竟要搞定这个流程还是有点难度的,云开发你又得有vue经验、还得有后端像数据库,node的一些概念,基本就全栈了,好在博主之前有egg全栈基础,网上云开发资料又少,全得博主去拼来猜,来试,博主都35了,后面不一定有命来给你试这些东西,你们都自己学着猜下,学会长大吧,趁我现在脑子没坏,能帮你们几年看命了,你们有点良心,博主主页左边那个公众号能关注的关注个,公众号发个“谢谢”,博主到时候看到应该会很感动。