Flask后端实践 连载十六 Flask实现微信Web端及APP端登录注册
Flask后端实践 连载十六 Flask实现微信Web端及APP端登录注册
tips:
- 本文将实现微信Web端和APP端登陆注册
- 本文基于python3编写
- 代码仓库
项目场景
某天,项目经理说,项目上除了本身自带的登陆注册,也需要第三方的登陆注册。方便用户使用我们的产品。于是便开始加上微信登陆注册的功能。
实现流程
- 前端页面拉取微信授权二维码
- 用户扫码确认授权。
- 前端将授权码发送到后端。
- 后端将授权码发送到微信平台验证,获取用户信息及授权信息。
- 比较本平台用户信息,实现用户登陆和注册。
前置条件
- 安装
flask
、flask-sqlalchemy
、PyMySQL
- 在微信开放平台申请了账户并成为开发者。
- 创建网站应用和移动应用,申请成功之后会下发
appid
和secret
,web和app的appid
、secret
不一样。 - 数据库设计
user(用户表,存储用户信息)
字段 类型 含义 id int 用户主键ID name string 用户名称 age int 年龄 … … … user_login_method(用户登陆方式表,存储不同登陆方式)
字段 类型 含义 id int 用户登陆方式主键ID user_id int 用户主键ID login_method string 用户登陆方式,WX微信,P手机 identification string 用户登陆标识,微信ID或手机号 access_code string 用户登陆通行码,密码或token … … …
- 映射数据库映射数据库到
model.py
from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()class User(db.Model):"""用户表"""__tablename__ = 'user'id = db.Column(db.Integer, autoincrement=True, primary_key=True)# 用户姓名name = db.Column(db.String(20), nullable=False) # 用户年龄age = db.Column(db.Integer, nullable=False) class UserLoginMethod(db.Model):"""用户登陆验证表"""__tablename__ = 'user_login_method'# 用户登陆方式主键IDid = db.Column(db.Integer, autoincrement=True, primary_key=True) # 用户主键IDuser_id = db.Column(db.Integer, nullable=False) # 用户登陆方式,WX微信,P手机 login_method = db.Column(db.String(36), nullable=False) # 用户登陆标识,微信ID或手机号identification = db.Column(db.String(36), nullable=False) # 用户登陆通行码,密码或tokenaccess_code = db.Column(db.String(36), nullable=True)
实现过程
前端拉取微信认证授权二维码,参考网站应用微信登录开发指南。此处只需要第一步,用户扫码确认之后获取到code传入后端。
获取授权凭证
wx_login_or_register.get_access_code
import json from urllib import parse, requestfrom model import UserLoginMethod, User, dbdef get_access_code(code, flag):"""获取微信授权码:param code:前端或app拉取的到临时授权码:param flag:web端或app端:return:None 或 微信授权数据"""# 判断是web端登陆还是app端登陆,采用不同的密钥。if flag == "web":appid = "web_appid"secret = "web_secret"elif flag == "app":appid = "app_appid"secret = "app_secret"else:return Nonetry:# 把查询条件转成url中形式fields = parse.urlencode({"appid": appid, "secret": secret,"code": code, "grant_type": "authorization_code"})# 拼接请求链接url = 'https://api.weixin.qq.com/sns/oauth2/access_token?{}'.format(fields) print(url)req = request.Request(url=url, method="GET")# 请求数据res = request.urlopen(req, timeout=10)# 解析数据access_data = json.loads(res.read().decode())print(access_data)except Exception as e:print(e)return None# 拉取微信授权成功返回# {# "access_token": "ACCESS_TOKEN", "expires_in": 7200,"refresh_token": "REFRESH_TOKEN",# "openid": "OPENID","scope": "SCOPE"# }if "openid" in access_data:return access_data# 拉取微信授权失败# {# "errcode":40029,"errmsg":"invalid code"# }else:return None
获取微信用户信息
wx_login_or_register.get_wx_user_info
def get_wx_user_info(access_data: dict):"""获取微信用户信息:return:"""openid = access_data.get("openid")access_token = access_data.get("access_token")try:# 把查询条件转成url中形式fields = parse.urlencode({"access_token": access_token, "openid": openid})# 拼接请求链接url = 'https://api.weixin.qq.com/sns/userinfo?{}'.format(fields)print(url)req = request.Request(url=url, method="GET")# 请求数据,超时10sres = request.urlopen(req, timeout=10)# 解析数据wx_user_info = json.loads(res.read().decode())print(wx_user_info)except Exception as e:print(e)return None# 获取成功# {# "openid":"OPENID",# "nickname":"NICKNAME",# "sex":1,# "province":"PROVINCE",# "city":"CITY",# "country":"COUNTRY",# "headimgurl": "test.png",# "privilege":[# "PRIVILEGE1",# "PRIVILEGE2"# ],# "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"## }if "openid" in wx_user_info:return wx_user_info# 获取失败# {"errcode":40003,"errmsg":"invalid openid"}else:return None
验证本地用户信息
wx_login_or_register.login_or_register
,关键的是比较微信用户信息中的unionid
。def login_or_register(wx_user_info):"""验证该用户是否注册本平台,如果未注册便注册后登陆,否则直接登陆。:param wx_user_info:拉取到的微信用户信息:return:"""# 微信统一IDunionid = wx_user_info.get("unionid")# 用户昵称nickname = wx_user_info.get("nickname")# 拉取微信用户信息失败if unionid is None:return None# 判断用户是否存在与本系统user_login = db.session(UserLoginMethod). \filter(UserLoginMethod.login_method == "WX",UserLoginMethod.identification == unionid, ).first()# 存在则直接返回用户信息if user_login:user = db.session.query(User.id, User.name).\filter(User.id == user_login.user_id).first()data = dict(zip(user.keys(), user))return data# 不存在则先新建用户然后返回用户信息else:try:# 新建用户信息new_user = User(name=nickname, age=20)db.session.add(new_user)db.session.flush()# 新建用户登陆方式new_user_login = UserLoginMethod(user_id=new_user.id,login_method="WX",identification=unionid,access_code=None)db.session.add(new_user_login)db.session.flush()# 提交db.session.commit()except Exception as e:print(e)return Nonedata = dict(id=new_user.id, name=User.name)return data
Flask接口
from flask import Flask from wx_login_or_register import get_access_code, get_wx_user_info, login_or_register from model import dbapp = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"]='mysql+pymysql://root:mad123@localhost:3306/test?charset=utf8mb4' # 注册数据库连接 db.app = app db.init_app(app)@app.route("/testWXLoginOrRegister",methods=["GET"]) def test_wx_login_or_register():"""测试微信登陆注册:return:"""# 前端获取到的临时授权码code = request.args.get("code") # 标识web端还是app端登陆或注册flag = request.args.get("flag")# 参数错误if code is None or flag is None:return "参数错误"# 获取微信用户授权码access_code = get_access_code(code=code, flag=flag)if access_code is None:return "获取微信授权失败"# 获取微信用户信息wx_user_info = get_wx_user_info(access_data=access_code)if wx_user_info is None:return "获取微信授权失败"# 验证微信用户信息本平台是否有,data = login_or_register(wx_user_info=wx_user_info)if data is None:return "登陆失败"return dataif ___name__ =="__main__":app.run()
测试访问
http://127.0.0.1:5000/testWXLoginOrRegister
即可。
总结
- 本文大致实现了微信web和app端的登陆注册,具体需求具体分析。
- 下一篇将介绍Flask实现手机验证码登录注册
Flask后端实践 连载十六 Flask实现微信Web端及APP端登录注册相关推荐
- Flask后端实践 连载十八 Flask输出PDF报表
Flask后端实践 连载十八 Flask输出PDF报表 tips: 简单实现Flask输出PDF报表 本文基于python3编写 代码仓库 项目场景 由于项目是工程上的使用,不仅需要对采集的数据进行分 ...
- Flask后端实践 连载十四 Flask输出Word报表
Flask后端实践 连载十四 Flask输出Word报表 tips: 简单实现Flask输出Word报表 本文基于python3编写 代码仓库 项目场景 由于项目是工程上的使用,不仅需要对采集的数据进 ...
- Flask后端实践 连载十三 Flask输出Excel报表
Flask后端实践 连载十三 Flask输出Excel报表 tips: 简单实现Flask输出Excel报表 本文基于python3编写 代码仓库 项目场景 由于项目是工程上的使用,不仅需要对采集的数 ...
- Redis进阶实践之十六 Redis大批量增加数据
原文:Redis进阶实践之十六 Redis大批量增加数据 一.介绍 有时候,Redis实例需要在很短的时间内加载大量先前存在或用户生成的数据,以便尽可能快地创建数百万个键.这就是所谓的批量插入,本文档 ...
- 单反相机的传奇—佳能单反50年辉煌之路(连载十六)
连载十六:执着--旁轴的坚持 引言:旭光学在单反上的惹眼表现,不可能让其他相机大厂无动于衷,然而以高档旁轴相机起家的佳能,面对徕卡和日本光学的远击近攻,仍然在旁轴相机的开发上不遗余力,并且获得了意想不 ...
- 【转载】 javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册 - 孤傲苍狼 - 博 http://www.cnblogs.com/xdp-gacl/
javaweb学习总结(二十二)--基于Servlet+JSP+JavaBean开发模式的用户登录注册 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+Ja ...
- Flask后端开发(二) - Flask的练习(入门)
建议食用官方文档:Welcome to Flask - Flask Documentation (2.1.x)https://flask.palletsprojects.com/ 前言:避免文章篇幅过 ...
- fastreport masterdata每页都显示_ALIENTEK 阿波罗 STM32F767 开发板资料连载十六章 OLED 显示实验...
1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 http://weixi ...
- 编译器之后端原理(三十六)
一.编译器的后端技术 1. 编译器的前端技术,重点是让编译器能够读懂程序,无结构的代码文本经过前端的处理以后,就变成了Token.AST和语义属性.符号表等结构化的信息,基于这些信息,可以实现简单的脚 ...
最新文章
- Nat. Mach. Intel. | IBM RXN: 深度学习在化学反应分类上大放异彩
- 驭下术:如何让下属老实听话?用这3招,让你不怒自威
- MySQL优化—工欲善其事,必先利其器之EXPLAIN
- MFC:怎么将程序窗口最小化到系统托盘
- php mysql随机记录,php – 从MySQL中选择可变数量的随机记录
- 【渝粤教育】国家开放大学2018年秋季 0109-21T公司财务 参考试题
- webstorm使用技巧
- C语言第五次博客作业
- 【Python】 [基础] 条件判断 与 循环 与dict和set
- 速成pytorch学习——4天中阶API示范
- Egret 之 消除游戏 开发 PART 6 Egret elimination game development PART 6
- mysql统计某一个数据库中有几张表
- 59 | 测试专栏特别放送 | 答疑解惑第七期
- html + css 实现淘宝首页(静态页面)
- FOI冬令营 Day1
- 人脸识别技术和人脸识别特征
- 输出边长为n的正六边形(c语言)
- 科大奥锐干涉法测微小量实验的数据,大学物理实验报告答案大全(实验数据)
- win7开不了机按f8修复计算机没反应,win7开不了机按f8没用怎么办
- std::cunction() 简单描述