【Flask开发】嘿马文学web完整flask项目第3篇:2.用户认证,2.用户认证【附代码文档】

举报
程序员一诺python 发表于 2025/07/13 13:52:28 2025/07/13
【摘要】 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.补充

教程总体简介:2.用户认证、Json Web Token(JWT)、3.书架、4.分类、5.搜索、6.小说、7.浏览记录、8.配置、9.部署、10.补充

https://gitee.com/yinuo112/Backend/blob/master/Flask/嘿马文学web完整flask项目/note.md


全套教程部分目录:

2.用户认证

  • 微信平台

  • JWT

  • 用户认证

  • 用户登录

2.3用户登录

  • 在applet_app/user.py文件中实现业务。

1-1 用户登录接口设计

  • 接口名称:用户登录
  • 接口路径:/user/login
  • 请求方法:POST
  • 请求参数:
参数名称 参数类型 是否必须 参数位置 参数说明
Content-Type True 请求头 数据类型application/json
envryptedData string True body 包括用户信息的加密数据,见微信开发文档,[
iv string True body 加密字符的初始向量
code string True body 用户登录凭证。开发者需要在开发者服务器使用code换取openid和session_key 等信息
  • 返回数据:
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
  /*
  * jwt token
  */
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZX0.OLvs36KmqB9cmsUrMpUutfhV52_iSz4bQMYJjkI_TLQ",

  /*
  * 用户信息
  */
  "userInfo": {
    "uid": "199282123", // 用户id
    "gender": 1, // 1  0 
    // 头像
    "avatarUrl": "
  },

  /*
  * 阅读配置
  */
  "config": {
    "preference": "0", // 0  1 
    "brightness": 90, // 10~100 亮度
    "fontSize": "18", // 字号
    "background": "B1", // B1 ~ B6 内置背景
    "turn": "T1" // T1 仿真 T2 平滑 T3  翻页模式
  }
}

1-2 代码实现

1、创建蓝图

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from flask import Blueprint

user_bp = Blueprint('user', __name__)

2、第三方登录

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@user_bp.route("/login",methods=['POST'])
def login():
    """ 第三方登录 """
    # code 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 auth.code2Session,
    # 使用 code 换取 openid 和 session_key 等信息
    code = request.json.get('code', '')
    # iv 加密算法的初始向量
    iv = request.json.get('iv', '')
    # encryptedData 包括敏感数据在内的完整用户信息的加密数据
    encryptedData = request.json.get('encryptedData', '')

    if not iv or not encryptedData or not code:
        return jsonify(msg='参数有误'), 403
    data = wxauth.get_wxapp_session_key(code)
    print('data', data)
    if 'session_key' not in data:
        return jsonify(msg='获取session_key失败', data=data), 500
    user_info = wxauth.get_user_info(encryptedData, iv, data['session_key'])
    if 'openId' not in user_info:
        return jsonify(msg='获取用户信息失败', user_info=user_info), 403

    user = User.query.filter_by(openId=user_info.get('openId')).first()
    if not user:
        user = User(user_info)
        db.session.add(user)
        db.session.flush()

        # 书架增加随机书籍-----后面完成
        # _add_book_shelf(user.id, user.gender)

    else:
        # 更新用户信息
        user.update_info(user_info)
        db.session.commit()
    # 生成jwt token
    token = _generate_tokens(user.id)

    ret_data = {
        "token": token,
        "userInfo": {
            "uid": user.id,
            "gender": user.gender,
            "avatarUrl": user.avatarUrl
        },
        "config": {
            "preference": user.preference,
            "brightness": user.brightness,
            "fontSize": user.fontSize,
            "background": user.background,
            "turn": user.turn
        }
    }
    return jsonify(ret_data)

3、为了后续项目功能演示,可以添加测试用户,用来测试功能。

  • 定义视图,添加测试用户
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@user_bp.route('/tmp_add_user', methods=['POST'])
def tmp_add_user():
    """
    添加测试用户
    :return:
    """
    data = dict(
        openId='1'*32,
        nickName='测试用户002',
        gender=1,
        city='广州市',
        province='广东省',
        country='中国',
        avatarUrl='default'
    )
    user = User(data)
    db.session.add(user)
    db.session.commit()
    # 后面完成
    # _add_book_shelf(user.id, user.gender)

    ret_data = {
        'msg': '添加成功',
        'user_id': user.id,
    }
    return jsonify(ret_data)
  • 登录接口测试代码:
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@user_bp.route('/tmp_login')
def tmp_login():
    """
    登录测试接口
    :return:
    """
    user_id = request.args.get('user_id')
    user = User.query.get(user_id)

    # 生成jwt token
    token = _generate_tokens(user_id)

    ret_data = {
        "token": token,
        "userInfo": {
            "uid": user.id,
            "gender": user.gender,
            "avatarUrl": user.avatarUrl
        },
        "config": {
            "preference": user.preference,
            "brightness": user.brightness,
            "fontSize": user.fontSize,
            "background": user.background,
            "turn": user.turn
        }
    }
    return jsonify(ret_data)

5、使用postman对接口进行测试:

  • 查看MySQL数据库,确认用户添加成功。

2.4用户认证

1-1 校验用户

  • 用户登录完成后,在项目的后续接口中,有些需要用户登录才能访问的接口,所以,需要校验用户身份信息。
  • 我们需要在每次请求前,从请求的JWTtoken的payload中取出用户id,用来校验用户权限,可以通过请求钩子实现,在项目目录/lib/middlewares.py文件,具体见代码:
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def before_request():
    g.user_id = None
    authorization = request.headers.get('Authorization')
    print(authorization)
    payload = verify_jwt(authorization)
    print(payload)
    if payload:
        g.user_id = payload['user_id']

1-2 登录验证装饰器

  • 取出用户信息后,我们可以通过装饰器的形式实现用户权限校验,在后续接口中,如果需要用户权限校验,直接添加login_required装饰器即可。

  • 具体见代码:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from functools import wraps
from flask import g, jsonify

def login_required(func):
      # wraps的作用让被装饰器装饰的函数的属性不发生变化。
    @wraps(func)
    def wrapper(*args, **kwargs):
        if not g.user_id:
            return jsonify({'msg': 'token error'}), 401
        return func(*args, **kwargs)
    return wrapper

2.用户认证

  • 微信平台

  • JWT

  • 用户认证

  • 用户登录

3.1书架列表

  • 在applet_app/mybooks.py文件中实现业务。

1-1 书架列表的基本业务:

  • 用户必须登录,可以添加我们前面实现登录验证装饰器。
  • 默认查询书架所有书籍,倒序排序。
  • 如果书架没有书籍,查询书籍数据库,随机挑选5本书籍,存入书架中。
  • 如果书架有书籍,返回书籍数据。

2-2 代码实现

1、创建蓝图

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from flask import Blueprint

mybooks_bp = Blueprint('mybooks', __name__)

2、定义视图

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@mybooks_bp.route('/')
@login_required
def mybooks_list():
    """
    我的书架-列表
    :return:
    """
    mybooks = BookShelf.query.filter_by(user_id=g.user_id).order_by(BookShelf.created.desc()).all()
    data = []
    if not mybooks:
        books = Book.query.all()
        bs_books = random.sample(books, 5)
        for book in bs_books:
            bs = BookShelf(user_id=g.user_id,
                           book_id=book.book_id,
                           book_name=book.book_name,
                           cover=book.cover)
            db.session.add(bs)
            data.append({
                'id': book.book_id,
                'imgURL': ' book.cover),
                'title': book.book_name
            })
        db.session.commit()
        return jsonify(data)
    else:
        for bs in mybooks:
            data.append({
                'id': bs.book_id,
                'imgURL': ' bs.cover),
                'title': bs.book_name
            })
        return jsonify(data)

3、使用postman对接口进行测试:

3.2书架管理

  • 在applet_app/mybooks.py文件中实现业务。
  • 书架的业务,主要是添加和删除书籍。

1-1 添加书籍的基本业务

  • 添加登录验证装饰器。
  • 需要传入参数书籍id
  • 查询书籍表,确认书籍的存在。
  • 查询书架表,如果书架上没有该书籍,添加书籍。
  • 否则,返回该书籍已在书架中。

1-2 代码实现

1、定义蓝图

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from flask import Blueprint

mybooks_bp = Blueprint('mybooks', __name__)

2、定义视图类 ```python

定义路由,书架管理--添加书籍

@login_required @mybooks_bp.route("/",methods=['POST']) def add_book(book_id): """ book_id:url固定参数,必须作为视图参数直接传入,Flask中使用转换器进行处理,默认的数据类型是str; :return: """ # 1.添加登录验证装饰器 user_id = g.user_id # 2.接收参数,书籍id # 3.根据书籍id,查询书籍表,确认数据的存在 book = Book.query.filter(Book.book_id==book_id).first() # 确认查询结果 if not book: return jsonify(msg='书籍不存在'),404 # 4.查询书架表,确认该书在书架中是否存在 book_shelf = BookShelf.query.filter(BookShelf.user_id==user_id,BookShelf.book_id==book_id).first() # 判断书架的查询结果 if not book_shelf: # 5.如果书架中不存在,添加书籍 bk_shelf = BookShelf( user_id=user_id, book_id=book.book_id, book_name=book.book_name, cover=book.cover ) db.session.add(bk_shelf) db.session.commit() # 返回添加成功

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。