uniCloud 微信小程序实现微信登录和token验证

我们主要使用uniapp + uniCloud在没有后端的情况下实现小程序登录的整个过程,从而了解云函数、

学前准备

  1. 个人也是可以注册小程序的,只是有些功能不能使用

  2. 需要准备一个未注册过微信公众号和小程序的邮箱

  3. 前往注册小程序注册

  4. 获取AppID 和AppSecret

注册一个uniCloud

https://unicloud.dcloud.net.cn/如果您还未开通过uniCloud,请在web界面开通https://unicloud.dcloud.net.cn/

然后在开发之前我们需要详细了解一下小程序的登录流程

小程序登录流程

这图的意思是先要在小程序端通过wx.login获取到code,然后再通过http请求发送code到开发者服务器,然后再由开发者服务器通过http请求发送相关参数到微信接口服务器获取到openid. 开发者服务器获取到openid之后,便可以做相关操作,比如入库注册会员,然后再返回相关的数据状态给小程序端,一般是生成一个token返回给小程序端,小程序端拿到token,缓存起来,在请求相关接口的时候在http的header里带上token。 现在有了云函数,开发者服务器部分的工作则可以由前端来完成,这也是云开发的相关过程。 比如上述的小程序登录过程,小程序端获取到code之后,不再请求开发者服务器的api,而是请求一个云函数,然后再云函数里通过云函数提供的http请求工具函数去请求微信接口服务器获取openid,然后在云函数里把相关的数据进行入云数据库的操作,再把相关数据返回给小程序端。

创建uniCloud项目

按uniCloud官网文档指引建立一个uniCloud项目:https://doc.dcloud.net.cn/uniCloud/

学习阶段,服务商可以选择阿里云免费版

uniCloud实现微信登录

创建云空间

点击新建服务空间

我这里选择服务商是阿里云,每个账号可以选择一次免费版,根据个人情况选择服务商和套餐版本,然后点击立即购买即可拥有自己的云空间

关联云空间

点击uniCloud文件夹右键选择关联云服务空间

选择你自己创建的云空间关联即可

创建云数据库

新建登录云函数

云函数微信登录示例代码

'use strict';

//小程序的AppID 和 AppSecret
const appid = "********************"
const secret = "********************"
// 创建user数据表实例
const db = uniCloud.database()
const user = db.collection('user')

// 生成token和校验token公共模块
const {getToken,verifyToken} = require('wx-common')

exports.main = async (event, context) => {

    //获取用户openid和session_key
	const res = await uniCloud.httpclient.request('https://api.weixin.qq.com/sns/jscode2session', {
		method: 'GET',
		data: {
			appid: appid,
			secret: secret,
			js_code: event.code,// 客户端传递过来的code
			grant_type: 'authorization_code'
		},
		dataType: 'json'
	})
    //判断请求用户openid和session_key是否成功
	if (res.status === 200) {
        //成功返回的openid和session_key
		const wx_openid = res.data.openid
		const wx_session_key = res.data.session_key
		// 生成token
		const token = getToken(wx_openid)
        //查询数据库判断用户是否已经注册 根据openid查找
		const res_user = await user.where({
			openid: wx_openid
		}).get()
        //用户未注册存储用户信息
		if (res_user.data && res_user.data.length === 0) {
			user.add({
				avatarUrl: event.userinfo.avatarUrl,
				nickName: event.userinfo.nickName,
				gender: event.userinfo.gender,
				openid: wx_openid,
				session_key: wx_session_key,
				mobile:"",
				token:token
			})
		} else {
        //用户已经存在更新token和session_key
			user.where({
				openid: wx_openid
			}).update({
				session_key: wx_session_key,
				token:token
			})
		}
        //将需要的个人信息返回到客户端例如:头像 昵称 等
		return user.where({
			openid: wx_openid
		}).field({
			avatarUrl: true,
			gender: true,
			nickName: true,
			mobile:true,
			token:true,
		}).get()

	} else {
    //获取用户openid和session_key失败响应客户端
		return {
			msg: '获取微信服务失败',
			code: 500
		}
	}
};

生成token公共模块的创建和使用

1.在common目录下新建公共模块

新建公共模块

2.在wx-common目录下 npm i jsonwebtoken 下载依赖

3.示例代码

// 生成token方法
const jwt = require('jsonwebtoken')

// 密匙
const secret = '***'

//生成token
function getToken(value) {
	// sign(加密数据,加密辅助,过期时间(单位/s))
	return jwt.sign({value}, secret, {expiresIn: 10800});
}
//解密token
function verifyToken(token) {
	try {
		return jwt.verify(token,secret)
	}catch(e) {
		return false
	}
}
//导出方法
module.exports = {
	getToken,
	verifyToken
}

4.在需要使用公共模块的云函数右键管理公共模块或扩展依赖

5.选择刚才创建的公共模块

客户端代码的实现

在pages目录下新建login.vue

<!-- 登录按钮 -->
		<view class="btn_box">
			<button class="btn" open-type="getUserInfo" @getuserinfo="getUserInfo">登录</button> 
		</view>
// 获取授权
			getUserInfo() {
				uni.showModal({
					title:"使用微信一键登录",
					showCancel:true,
					cancelColor:"#000000",
					confirmColor:"#42b983",
					success:(success) => {
						if(success.confirm) {
							uni.showLoading({
								title:'登录中...'
							})
							uni.getUserProfile({
								desc:'获取用户信息,进行登录',
								success: (res) => {
                                    //调用登录函数
									this.getLogin(res.userInfo)
								}
							})
						}
						if(success.cancel) {
							uni.showToast({
								title: '用户取消登录!',
								icon:'none',
								duration: 2000
							});
						}
						
						
					}
				})
			},
			// 微信登录
			getLogin(userInfo) {
				uni.login({
					provider:'weixin',
					success: (res) => {
						// 调用云函数
						uniCloud.callFunction({
							name:'Login', // 云函数名称
							data:{ // 需要传递给云函数的参数
								userinfo:userInfo,
								code:res.code
							}
						}).then(ress => {
                            //判断是否返回了用户数据
							if(ress.result.affectedDocs != 0) {
                                //存储用户信息
								this.UpdaUserInfo(ress.result.data[0])
								// 存储token
								uni.setStorage({
									key:'Token',
									data:ress.result.data[0].token
								})
								uni.showToast({
									title:'登录成功',
									icon:'none',
									duration: 2000
								});
								setTimeout(() => {
									// 跳转首页
									uni.switchTab({
										url:'/pages/home/home'
									})
								},2000)
							}else {
								uni.showToast({
									title:'登录失败',
									icon:'none',
									duration: 2000
								});
							}
							uni.hideLoading()
							
							
						}).catch(err => {
							uni.showToast({
								title:'登录失败',
								icon:'none',
								duration: 2000
							});
						})
					} 
				})
			}
		
		},

封装公共请求方法

1.创建common目录和cloudApi.js

2.代码实现

// 公共请求方法
const http = (Name, Data = {}) => {
	return new Promise((resolve, reject) => {
		const token = uni.getStorageSync('Token')
		// 判断是否存在token
		if (!token) {
			uni.showToast({
				icon: 'error',
				title: '请先登录!',
				duration: 2000
			})
			// 返回登录页
			setTimeout(() => {
				uni.redirectTo({
					url: '/pages/login/login'
				})
			}, 2000)
		} else {
			// 用户已经登录(验证token合法性)
			uniCloud.callFunction({
				name: 'VerifyToken',
				data: {
					token: token,
				},
				success: (TokenRes) => {
					console.log("返回", TokenRes)
					if (TokenRes.result === false) {
						// token 过期
						uni.showToast({
							icon: 'error',
							title: '登录失效',
							duration: 2000
						})
						// 返回登录页
						setTimeout(() => {
							uni.redirectTo({
								url: '/pages/login/login'
							})
						}, 2000)
					} else {
						
							uniCloud.callFunction({
								name: FunctionName,
								data: FunctionData,
								success: (res) => {
									resolve(res)
								},
								fail: (err) => {
									reject(err)
								}
							})
						
					}
				}
			})

		}

	})

}


export default http

3.在main.js挂载

4.使用公共请求方法

最后

这也是我第一次个人云开发微信小程序,有问题可以一起探讨交流,欢迎各位大佬指正,谢谢!

  • 28
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

safe030

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值