教程总体简介:2. 目标 1.1产品与开发 1.2环境配置 1.3 运行方式 1.4目录说明 1.5数据库设计 2.用户认证 Json Web Token(JWT) 3.书架 4.1分类列表 5.搜索 5.3搜索-精准&高匹配&推荐 6.小说 6.4推荐-同类热门推荐 7.浏览记录 8.1配置-阅读偏好 8.配置 9.1项目部署uWSGI 配置 启动 9.部署 10.1异常和日志 10.补充 10.2 flask-restful 1.项目目录实现 3.数据库迁移: 1.JWT:json web token 2.jwt工具的封装 4.用户权限校验 5.登录验证装饰器 1.书架列表 2.书架管理 3.最后阅读 2.分类书籍列表 3.热门搜索 7.3小说-详情 2.小说目录 2.阅读偏好 3.阅读设置
完整笔记资料代码:https://gitee.com/yinuo112/Backend/tree/master/Flask/嘿马文学web完整flask项目/note.md
感兴趣的小伙伴可以自取哦~
全套教程部分目录:
部分文件图片:
2.用户认证
-
平台
-
JWT
-
用户认证
-
用户登录
2.1平台
1-1 小程序登录授权
- 调用 wx.login()获取 临时登录凭证code ,并回传到开发者服务器。
- 调用 auth.code2Session接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key。
-
小程序授权登录说明:
-
通过查看官方文档的小程序开发说明,小程序授权登录,需要获取登录凭证校验,通过wx.login(Object) 调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)。
- 登录凭证code:用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 auth.code2Session,使用 code 换取 openid 和 session_key 等信息。
- 会话密钥
session_key
是对用户数据进行加密签名的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。 - 临时登录凭证 code 只能使用一次。
1-2 授权说明
-
实现授权,获取用户信息。
-
小程序可以通过官方提供的登录功能来获取用户身份的标识。主要实现的就是通过小程序提供的 code 换取用户的 openid 和 session_key。用到的接口如下:
-
wx.login
- 调用此接口,以获取登录凭证(code),以用来换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key)。
- 如果接口调用成功,返回信息如下:
参数名 | 类型 | 参数说明 |
---|---|---|
errMsg | String | 调用结果 |
code | String | 用户允许登录后,回调内容会带上 code(有效期五分钟),开发者需要将 code 发送到开发者服务器后台,使用code 换取 session_key api,将 code 换成 openid 和 session_key |
-
开发者服务器使用登录凭证 code 获取 session_key 和 openid。其中 session_key 是对用户数据进行加密签名的密钥。
-
wx.getUserInfo
-
调用此接口,用来获取用户信息。
-
并用换取到的 openid 和 secret_key 作为自定义的登录状态。具体可以分为如下部分:
-
提供一个http接口,共小程序使用,传递code;
- 换取用户身份标识;
- 维护自定义的登录状态;
- 存储用户的openid。
1-2-1 开发原理
- 小程序通过wx.login API进行登录获取code,根据code获取openid需要在服务端完成,所以需要将code发送给服务端,并且带上授权临时票据code参数;
- 服务端通过code和appid、APPSecret获取到openid和SessionKey。
- 前端保存自定义登录态,获取用户信息时携带自定义登录态给后端。
1-2-2 服务端
- 接受小程序前端发送的请求,根据发送过来的code,以及服务端保存的AppId和APPSecret等向服务端发送请求,获取到sessionkey和openid,然后将二者关联起来保存到session存储器中(Redis),返回给前端key值。
- 接受小程序发送过来的key和用户基本信息,根据key从redis中获取openid,然后对数据库进行查询,若存在数据则封装后返回给前端,若无信息则向数据库中插入数据并返回给前端。
1-2-3 获取session_key(auth.code2Session)
- 请求地址: [
- 请求方法:GET
- 请求参数:
参数名 | 类型 | 是否必须 | 参数说明 |
---|---|---|---|
appid | string | True | 小程序appid |
secret | string | True | 小程序appSecret |
js_code | string | True | 登录时获取的code |
grant_type | string | True | 授权类型,此处只需填写 authorization_code |
- 返回结果:返回的是JSON数据包
属性 | 类型 | 说明 |
---|---|---|
openid | string | 用户唯一标识 |
session_key | string | 会话密钥 |
unionid | string | 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回, |
errcode | number | 错误码 |
errmsg | string | 错误信息 |
1-2-4 获取用户信息
- 用户授权登录后,我们可以通过调用平台wx.getUserInfo(Object object)获取用户信息,用来存储用户数据。
1、接口说明
参数名 | 类型 | 是否必须 | 参数说明 |
---|---|---|---|
withCredentials | boolean | False | 是否带上登录态信息。当 withCredentials 为 true 时,要求此前有调用过 wx.login 且登录态尚未过期,此时返回的数据会包含 encryptedData, iv 等敏感信息;当 withCredentials 为 false 时,不要求有登录态,返回的数据不包含 encryptedData, iv 等敏感信息。 |
lang | string | False | 显示用户信息的语言 |
success | function | False | 接口调用成功的回调函数 |
fail | function | False | 接口调用失败的回调函数 |
complete | function | False | 接口调用结束的回调函数(调用成功、失败都会执行) |
2、补充说明
-
encryptedData:包括敏感数据在内的完整用户信息的加密数据。
-
接口如果涉及敏感数据(如[wx.getUserInfo]( openId 和 unionId),接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据(encryptedData) 进行对称解密。
-
官方提供了四种编程语言C++、Node、PHP、Python的示例代码,可以自行下载。
-
iv:加密算法的初始向量。
-
开发者如果遇到因为 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 有效期作为自身登录态有效期,也可以实现自定义的时效性策略。
1.3 开发准备
- 注册账号,选择个人,成为开发者,小程序开发平台:[
- 实名认证:
- 提交确认信息:
- 查看AppID和AppSecret:
- 获取AppSecret:需要扫码确认。
Json Web Token(JWT)
1-1 JWT简介
JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。
官方定义:JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties
JWT是一个有着简单的统一表达形式的字符串:
头部(Header)
头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。 JSON内容要经Base64 编码生成字符串成为Header。
载荷(PayLoad)
payload的五个字段都是由JWT的标准所定义的。
- iss: 该JWT的签发者
- sub: 该JWT所面向的用户
- aud: 接收该JWT的一方
- exp(expires): 什么时候过期,这里是一个Unix时间戳
- iat(issued at): 在什么时候签发的
后面的信息可以按需补充。 JSON内容要经Base64 编码生成字符串成为PayLoad。
签名(signature)
这个部分header与payload通过header中声明的加密方式,使用密钥secret进行加密,生成签名。 JWS的主要目的是保证了数据在传输过程中不被修改,验证数据的完整性。但由于仅采用Base64对消息内容编码,因此不保证数据的不可泄露性。所以不适合用于传输敏感数据。
1-2 JWT的Python库
1、独立的JWT Python库
-
itsdangerous
-
JSONWebSignatureSerializer
-
TimedJSONWebSignatureSerializer (可设置有效期)
-
pyjwt
[
2、安装
$ pip install pyjwt
3、使用示例
>>> import jwt>>> encoded_jwt = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256')
>>> encoded_jwt
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg'>>> jwt.decode(encoded_jwt, 'secret', algorithms=['HS256'])
{'some': 'payload'}
4、项目封装
import jwt
from flask import current_appdef generate_jwt(payload, expiry, secret=None):_payload = {'exp': expiry}_payload.update(payload)if not secret:secret = current_app.config['JWT_SECRET']token = jwt.encode(_payload, secret, algorithm='HS256')return token.decode()def verify_jwt(token, secret=None):if not secret:secret = current_app.config['JWT_SECRET']try:payload = jwt.decode(token, secret, algorithm=['HS256'])except jwt.PyJWTError:payload = Nonereturn payload