Flask与微信小程序登录(后端)
开发微信小程序时,接入小程序的授权登录可以快速实现用户注册登录的步骤,是快速建立用户体系的重要一步。这篇文章将介绍 python + flask + 微信小程序实现用户快速注册登录方案(本文主要进行后端逻辑的梳理,小程序端逻辑只写了必要的部分,如有需要,请点击连接阅读官方开发文档)
官方给出的微信小程序登录时序图如下:
这个流程分为两大部分:
- 小程序使用 wx.login() API 获取 code,并由开发者后端服务器换取open_id 和 session_key,小程序使用 wx.getUserInfo() API 获取 encryptedData 和 iv,然后将这三个信息发送给开发者服务器服务器。
- 开发者服务器获取到 code、encryptedData和 iv 后,将 session_key 利用 encryptedData 和 iv 解密,在服务端获取用户信息。根据用户信息返回 jwt 数据,完成登录状态。
小程序登录流程梳理
1 小程序端调用wx.login
小程序通过wx.login获取微信的 code,然后将这个 code 发送给开发者服务器。
返回值
| 属性 | 类型 | 说明 |
|---|---|---|
| code | String | 用户允许登录后,回调内容会带上 code(有效期五分钟) |
2 判断用户是否授权
小程序端可以通过 wx.getSetting 接口获取用户当前的授权状态
- 如果用户已经授权,则直接发起登录请求
- 如果用户没有授权,则调用 wx.authorize 或
引导用户关注公众号来获得授权。 - 如果用户不予授权,则登录失败。
3 小程序端访问 wx.getUserInfo
小程序端调用 wx.getUserInfo API 来获得用户信息(该接口的调用需要获得用户授权)
接口success 时返回参数如下:
| 参数名 | 类型 | 说明 |
|---|---|---|
| userInfo | OBJECT | 用户信息对象,不包含 openid 等敏感信息。 |
| rawData | String | 不包括敏感信息的原始数据字符串,用于计算签名。 |
| signature | String | 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息 |
| encryptedData | String | 包括敏感数据在内的完整用户信息的加密数据,详细见加密数据解密算法 |
| iv | String | 加密算法的初始向量,详细见加密数据解密算法 |
将这些第一步获得的js_code和这里获得的 rawData, signature, encryptedData, iv一起打包传入开发者后端。
4 开发者服务器访问code2session
开发者服务器接收到 code 之后,会进行封装处理,通过code2Session这个api接口来获取真正需要的微信用户的登录态session_key和 openid 和 unionid。
- 准确来说
session_key才是真正的微信登录态信息,但是把openid和unionid加起来一起理解,也可以笼统地理解为这些都是微信的登录态信息。
请求参数
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
| appid | string | 是 | 小程序 appId | |
| secret | string | 是 | 小程序 appSecret | |
| js_code | string | 是 | 登录时获取的 code | |
| grant_type | string | 是 | 授权类型,此处只需填写 authorization_code |
返回值(返回JSON数据包)
| 属性 | 类型 | 说明 |
|---|---|---|
| openid | string | 用户唯一标识 |
| session_key | string | 会话密钥 |
| unionid | string | 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回 |
| errcode | number | 错误码 |
| errmsg | string | 错误信息 |
这时,服务器需要判断返回的JSON数据包是否包含unionid:
- 如果包含,则说明用户已经授权(关注过同一主体公众号,或者已经登录过小程序在后端保存unionid)
- 如果不包含,返回第1步,提醒用户授权
5 开发者服务器校验用户信息
encryptedData 解密后为以下 json 结构,详见加密数据解密算法
{
"openId": "OPENID",
"nickName": "NICKNAME",
"gender": GENDER,
"city": "CITY",
"province": "PROVINCE",
"country": "COUNTRY",
"avatarUrl": "AVATARURL",
"unionId": "UNIONID",
"watermark":
{
"appid":"APPID",
"timestamp":TIMESTAMP
}
}
解密脚本实例连接:https://res.wx.qq.com/wxdoc/dist/assets/media/aes-sample.eae1f364.zip
数据签名校验
为了确保开放接口返回用户数据的安全性,微信会对明文数据进行签名。开发者可以根据业务需要对数据包进行签名校验,确保数据的完整性。
- 通过调用 wx.getUserInfo 借口获取数据时,接口会同时返回 rawData、signature,其中 signature = sha1( rawData + session_key )
数据签名校验具体步骤
- 如果
code为空,返回登录失败。 - 如果
code不为空,且rawData不为空,需要进行签名校验:- 使用
code,appid、app_secret请求code2session接口获得session_key和openid- 如果接口失败,响应
ERR_SESSION_KEY_EXCHANGE_FAILED
- 如果接口失败,响应
- 使用签名算法通过
rawData和session_key计算签名signature2 - 对比
signature和signature2- 签名不一致,响应
ERR_UNTRUSTED_RAW_DATA - 签名一致,解析
rawData为wxUserInfo- 把
openid写入到wxUserInfo - 把
(code, wxUserInfo)缓存到 Redis - 更新用户数据库信息(unionid为pk)
- 进入下一环节
- 把
- 签名不一致,响应
- 使用
- 如果
code不为空,但rawData为空,从 Redis 根据code查询缓存的用户信息- 找到用户信息,进入下一环节
- 没找到用户信息(可能是过期),响应
ERR_SESSION_EXPIRED
6 生成自定义登录状态(使用JWTtoken)
开发者服务器需要自己生成一个自定义的登录态(例如业务 token或者 session)来保存这些微信服务器返回来的微信登录态相关信息(session_key和 openid 和 unionid),并且做关联处理,然后返回给小程序客户端。
- 关联处理就是你的自定义登录态和微信的登录态相关联,这样的话就不需要维护多个登录态,只需要维护一个就可以了。
- 关联处理之后需要将这个自定义登录态信息保存起来,可以放到数据库或者本地文件或者 例如 redis 之类的缓存服务里面,以便方便后续使用,而不需要每次都请求微信服务器(微信服务器对这个请求的频率是有限制的)。
- 自定义登录态的信息不仅可以包含 token,也可以包含一些用户权限信息,或者其他信息,因为是自定义的登录态,维护也是很自定义的。
7 小程序端将服务器端生成的token储存
小程序客户端接收到返回的自定义登录态信息,从而判断用户是否登录成功,登录成功的话,就将自定义登录态信息保存到本地的存储。到这里,登录就完成了。
- 本地的存储可以是微信小程序提供的
app.globaldata,也可以是localstoage,注意,小程序不支持cookie。 - 保存到本地存储的好处就是,后续使用的这个自定义登录态就不需要再次跟服务器进行交互来获取了,只需要调用本地存储就行了,这里是为了优化性能和避免浪费资源。
8 小程序访问业务接口逻辑
小程序客户端访问业务接口的时候,携带之前保存到本地存储的自定义登录态信息进行对开发者服务器(业务接口服务器)访问。
开发者服务器的业务接口接收到请求,并且请求里面携带了自定义的登录态,通过校验之后,会返回相关信息。
校验登录是将小程序客户端携带过来的自定义登录态和开发者服务器缓存起来的自定义登录态进行对比,会去确认是否和用户的
openid或者unionid和session_key相匹配。- 如果匹配,就可以马上返回业务信息。
- 如果不匹配,告知小程序客户端无法访问业务接口,要求用户重新登录。
- 如果匹配结果是自定义登录态超时了,告知小程序客户端需要重新运行登录逻辑。
- 如果是匹配结果是自定义登录态没有超时,但是微信登录态超时了,那么要求开发者服务器就会再次发起
code2Session进行微信登录态更新。
由于我们的小程序使用微信号作为小程序的账号,如果需要使用自定义的账号,则需要再加上注册的api和关联账号的逻辑。
流程总结
code是微信用户的登录临时凭证,是打开小程序登录的时候获取的只属于这个微信用户的登录凭证,需要注意的是,这个登录凭证只供微信小程序使用的。且同一个每一次登录时获得的code都不同。这个code的存活时间一般是5分钟左右,他的最大作用就是确定是来源自哪一个微信用户来打开,是为了后续生成一个微信登录态session_key而准备的。session_key是微信用户在小程序里面的登录态信息,这是微信给这个用户颁发的一个登录session。这个session一直存活直到你关闭小程序。- 以前官方是返回固定的
expire_time的,但是后面取消了,官方的解释是:用户越频繁使用小程序,session_key有效期越长,初始有效期是3天,但是这个不一定是固定的,具体看业务需求,总的原则就是维护一个自定义登录态,自定义登录需要和微信登录态关联。
- 以前官方是返回固定的
openId,用户在微信里面的唯一标识,但是需要跟unionid进行一起理解。unioinId,如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。- 一般来说,
openId就是微信用户的唯一标识,但是因为微信产品很多,所以会出现多个微信产品使用不同的openId来识别同一个用户,所以建议是统一使用unioinid作为用户识别的依据,因为一般来说,一般的业务都会有公众号,所以unionid使用频率较高。
- 一般来说,
3rd_session是一般是指开发者服务器的登录态,本文中并没有使用这个概念,而是叫做自定义登录态或者直接说JWTtoken,官方文档或者其他一些博客中会提到它。实际上他们是相同的概念。- 当小程序登录态过期了,自定义登录态没过期的时候,那么就需要在小程序打开的时候先执行一次
wx.checkSession来检查,如果过期了,就本地执行登录操作,再让开发者服务器跟微信服务器交互,获取新的小程序登录态,然后关联到自定义登录态。 - 当小程序登录态没过期,自定义登录态过期了的时候,那么小程序客户端访问业务接口的时候,业务接口会告诉小程序客户端,你的自定义登录态超时了,然后小程序客户端会重新执行登录逻辑,然后通知开发者服务重新生成新的自定义登录态,然后关联之前还在使用的小程序登录态。
- 当二者都同时过期的时候,那就肯定要发起完整的重新登录了。
- 这样的好处是自定义登录态不需要重复创建,也能跟小程序登录态一起维护管理,达到资源合理利用的效果。
- 当小程序登录态过期了,自定义登录态没过期的时候,那么就需要在小程序打开的时候先执行一次
- 一般自定义登录态的管理都会使用类似 redis 之类的东西来进行管理的,这里也涉及到一个自定义登录态的缓存策略,缓存起来,在一定时间内不需要重新创建自定义登录态,达到优化性能的效果。
登录态的验证
1 在每一次开启小程序的时候需要检查登录态
如果每次打开小程序都需要用户来登录显然是不合适的,如果用户上一次的登录态还没有过期,则应该视用户为已经登录。如果过期,才需要用户重新登录。
有2种方式来做:
- 方式一:小程序打开的时候先检查小程序本地是否有存储的自定义登录态,
- 如果没有,则代表是首次登录,要自动执行完整的登录流程,
- 如果有,则需要判断这个自定义登录态是否过期,可以是开发者服务器提供一个接口来检查,也可以是在这个自定义登录态数据里面加上过期时间,判断是否过期。
- 过期,则自动发起完整的登录流程。
- 不过期,就继续使用本地保存的自定义登录态。
- 方式二:小程序打开的时候先发起
wx.checkSession检查微信登录态是否过期:- 如果过期,则发起完整的登录流程。
- 如果不过期,则继续使用本地保存的自定义登录态。(如果本地的自定义登录态没有的话,那么也是要强制发起完整的登录流程的)
2 在每次业务请求时需要验证登录态
某些业务需要只有用户登录状态下才可以执行,所以,我们需要封装一个api来验证用户时候登录
实际上就是检查一下微信和自定义的登录态是否过期
参考链接
Flask与微信小程序登录(后端)的更多相关文章
- 微信小程序 - 登录(后端实现) | 授权(后端实现)
登录与授权 官方文档 一.登录 登录流程时序 说明: 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器. 调用 code2Session 接口,换取 用户唯一标识 Ope ...
- 微信小程序登录对接Django后端实现JWT方式验证登录
先上效果图 点击授权按钮后可以显示部分资料和头像,点击修改资料可以修改部分资料. 流程 1.使用微信小程序登录和获取用户信息Api接口 2.把Api获取的用户资料和code发送给django后端 3. ...
- 微信小程序 PHP后端form表单提交实例详解
微信小程序php后端form表单 https://www.cnblogs.com/tdalcn/p/7092716.html 1.小程序相对于之前的WEB+PHP建站来说,个人理解为只是将web放到了 ...
- 基于Shiro,JWT实现微信小程序登录完整例子
小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html ...
- Python flask构建微信小程序订餐系统
第1章 <Python Flask构建微信小程序订餐系统>课程简介 本章内容会带领大家通览整体架构,功能模块,及学习建议.让大家在一个清晰的开发思路下,进行后续的学习.同时领着大家登陆ht ...
- 全栈项目|小书架|微信小程序-登录及token鉴权
小程序登录 之前也写过微信小程序登录的相关文章: 微信小程序~新版授权用户登录例子 微信小程序-携带Token无感知登录的网络请求方案 微信小程序开通云开发并利用云函数获取Openid 也可以通过官方 ...
- Spring Security 整合 微信小程序登录的思路探讨
1. 前言 原本打算把Spring Security中OAuth 2.0的机制讲完后,用小程序登录来实战一下,发现小程序登录流程和Spring Security中OAuth 2.0登录的流程有点不一样 ...
- 微信小程序登录方案
微信小程序登录方案 登录程序 app.js 调用wx.login获取code 将code作为参数请求自己业务登录接口获取session_key 存储session_key 如果有回调执行回调 App( ...
- 微信小程序登录,获取code,获取openid,获取session_key
微信小程序登录 wx.login(Object object) 调用接口获取登录凭证(code).通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session ...
随机推荐
- ubuntu下如何检查nvidia显卡驱动是否安装OK?
答:使用sudo lshw -c video即可,笔者的输出如下: jello~$ sudo lshw -c video*-display description: VGA compatible co ...
- leetcode378 有序矩阵中第k小的元素
排序后取数组第k个元素,遍历需要n^2的复杂度,查找插入logn,时间复杂度O(n^2logn).方法很笨,完全就是STL过于牛x运行通过的. class Solution { public: int ...
- c# Selenium ExpectedConditions 不存在
Selenium中的显示等待指的是,等待某一元素出现或者等待页面加载完成后,才执行下一步.需要用到WebDriverWait类. 例如: , , )); var element = wait.Unti ...
- go 基础 结构体 接口 访问权限
package School type SchoolModel struct { Name string Address string StudentCount int Is985 bool } ty ...
- Redis 高级应用
Redis SAVE 命令用于创建当前数据库的备份 该命令将在 redis 安装目录中创建dump.rdb文件. 如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并 ...
- C# 反转单向链表
static void Main(string[] args) { Mynode mynode0 = new Mynode(); Mynode mynode1 = new Mynode(); Myno ...
- 《Visual Studio程序员箴言》笔记
还记得刚工作时看到某前辈用快捷键操作Visual Studio,赞叹不已,才发觉原来快捷键熟练了效率可以如此之高.后来,我在为一个经常使用的命令添加快捷键的时候又发现Visual Studio的快捷键 ...
- 【HANA系列】SAP HANA SQL从给定日期中获取分钟
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL从给定日 ...
- 【HANA系列】【第六篇】SAP HANA XS使用JavaScript(JS)调用存储过程(Procedures)
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第六篇]SAP HANA XS ...
- python爬虫概述
爬虫的使用:爬虫用来对网络的数据信息进行爬取,通过URL的形式,将数据保存在数据库中并以文档形式或者报表形式进行展示. 爬虫可分为通用式爬虫或特定式爬虫,像我们经常用到的搜索引擎就属于通用式爬虫,如果 ...