Flask简单调用Redis、MySQL和生成token及token验证

2023-11-05

项目地址:https://github.com/MasonYyp/myflask

1 安装python基础环境

# 安装flask
pip install flask

# 安装redis
pip install redis

# 安装操作MySQL的包
pip install flask-sqlalchemy
pip install pymysql
# 安装序列化包
pip install flask-marshmallow
pip install marshmallow-sqlalchemy


# 安装生成token相关的包
pip install pyjwt

# 安装生成验证码的包
pip install captcha

2 Docker安装redis和mysql

2.1 redis.conf

# redis.conf
# 可远程连接
# bind 127.0.0.1
# 解除保护模式
protected-mode no
# 数据持久化
appendonly yes
# 设置密码
requirepass 123456

2.2 创建redis容器

sudo docker run -itd \
--restart=always \
--name fl_redis \
-p 6379:6379 \
-v /home/fl_redis/redis.conf:/etc/redis/redis.conf \
-v /home/fl_redis/data:/data \
redis:6.2.2 redis-server /etc/redis/redis.conf

2.3 创建MySQL容器

# 安装MySQL,密码是123456
sudo docker run -itd \
--restart=always \
--name fl_mysql \
-p 3306:3306 \
-v /home/mysql/conf:/etc/mysql/conf.d \
-v /home/mysql/data:/var/lib/mysql \
-v /home/mysql/log:/var/log/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7

进入MySQL容器创建数据库

create database myflask default character set utf8mb4 collate utf8mb4_unicode_ci;

3 vue前端

3.1 前端页面

<template>
  <div class="login">
    <div>Login</div>
    <div class="lo_cont">
      <div>
        用户名:<el-input v-model="name" placeholder="请输入用户名"></el-input>
      </div>
      
      <div>
        密码:<el-input v-model="pwd" placeholder="请输入密码" show-password></el-input>
      </div>
      
      <div>
        验证码:<img v-bind:src="codeImgSrc"><el-input v-model="code" placeholder="请输入验证码"></el-input>
      </div>
      <el-button v-on:click="login">提交</el-button>
    </div>
  
  </div>
</template>

<script>

import axios from 'axios'

// 按需引入ElementUI组件
import 'element-ui/lib/theme-chalk/index.css' 
import { Input, Button } from 'element-ui'


export default {
  name: 'Login',
  props: {
    msg: String
  },
  components:{
    elInput: Input,
    elButton: Button
  },

  data:function(){
    return{
      name:"mason",
      pwd:"123456",
      code:"",
      codeKey: "",
      codeImgSrc: ""
    }
  },

  created:function(){
    this.get_captcha()
  },

  methods:{

    get_captcha: function(){
      axios.post("/flask/public/captcha").then(res=>{
        console.log(res.data)
        let data = res.data;
        this.codeImgSrc = data.code_img;
        this.codeKey = data.code_key;
      })
    },

    login: function(){
      let param = {
        name: this.name,
        pwd: this.pwd,
        code_key: this.codeKey,
        code: this.code
      }

      // 使用json方式传参
      axios.post("/flask/public/login", param).then(res=>{
        let token = res.data
        console.log(token);
      })
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

.lo_cont>>>.el-input{
  width: 30%;
}

</style>

3.2 截图

前端截图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UCayOZby-1663496733483)(Flask使用Redis存储tocken.assets/image-20220918172017664.png)]

4 flask工程

4.1 工程目录

在这里插入图片描述

4.2 代码

4.2.1 main
from flask import Flask

from route.interceptor import before_interceptor
from route.operate_blueprint import OperateBlueprint
from dao.base_db.mysql_db import init_mysql_db

app = Flask(__name__)


# 设置拦截器
@app.before_request
def route_interceptor():
    return before_interceptor()


# 初始化蓝本
operate_blueprint = OperateBlueprint(app)
operate_blueprint.init_blueprint()

# 初始化MySQL
init_mysql_db(app)


# Run the app
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
4.2.2 config目录
4.2.2.1 common.py
import os


def get_root_path():
    cur_path = os.path.abspath(os.path.dirname(__file__))
    root_path, _ = os.path.split(cur_path)

    return root_path
4.2.2.2 db_conf.py

class RedisConf:
    # 配置基本参数
    pwd = "123456"
    host = "192.168.108.100"
    port = 6379


class MysqlConf:
    acc = "root"
    pwd = "123456"
    host = "192.168.108.100"
    port = 3306
    db = "myflask"


redis_conf = RedisConf()
mysql_conf = MysqlConf()
4.2.3 dao目录
4.2.3.1 base_db.mysql_db.py
from flask import Flask
from config.db_conf import mysql_conf
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow

# 添加pymysql驱动,连接MySQL数据库
import pymysql
pymysql.install_as_MySQLdb()

# 创建MySQL单实例
mysql_db = SQLAlchemy()

# 创建Schema
mysql_schema = Marshmallow()


# 初始化MySQL数据库
def init_mysql_db(app: Flask):

    # 配置MySQL数据库url
    db_url = "mysql://" + mysql_conf.acc + ":" + mysql_conf.pwd + "@" + mysql_conf.host + ":" + str(mysql_conf.port) + "/" + mysql_conf.db
    app.config["SQLALCHEMY_DATABASE_URI"] = db_url

    # 关闭sqlalchemy自动跟踪数据库
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    # 显示底层执行的SQL语句
    app.config['SQLALCHEMY_ECHO'] = True

    # 解决‘No application found. Either work inside a view function or push an application context.’
    app.app_context().push()

    # 初始化app
    mysql_db.init_app(app)

    # 初始化schema
    mysql_schema.init_app(app)


# 初始化table
def init_table():
    # 删除表
    mysql_db.drop_all()
    # 创建表
    mysql_db.create_all()
4.2.3.2 base_db.redis_db.py
import redis
from config.db_conf import redis_conf


class RedisDB:

    # 初始化redis
    def __init__(self):
        # 设置主机、端口号和密码
        redis_pool = redis.ConnectionPool(host=redis_conf.host, port=redis_conf.port, password=redis_conf.pwd, decode_responses=True)
        self.__strict_redis = redis.StrictRedis(connection_pool=redis_pool)

    # 在redis中添加键值,并设置过期时间
    def set(self, key, value, expiry):
        self.__strict_redis.set(name=key, value=value, ex=expiry)

    # 获取值
    def get(self, key):
        return self.__strict_redis.get(name=key)

    # 获取键值的剩余时间
    def ttl(self, key):
        # Time To Live
        return self.__strict_redis.ttl(name=key)


# 设置单例模式
redis_db = RedisDB()
4.2.3.3 base_db.mysql_db.model.user_model.py
from dao.base_db.mysql_db import mysql_db as db


# 创建用户表
class User(db.Model):
    # 用户
    __tablename__ = "tf_user"

    id = db.Column(db.Integer, nullable=False, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32), nullable=False, unique=True)
    pwd = db.Column(db.String(32), nullable=False)

    def __repr__(self):
        # 显示对象中的信息
        return "User object: name=%s" % self.name
4.2.3.4 base_db.mysql_db.schema.user_schema.py
from dao.base_db.mysql_db import mysql_schema as ma
from dao.mysql_dao.model.user_model import User

"""
# 序列化方法1
# 需要
注意flask-marshmallow的版本:
    flask-marshmallow<0.12.0
    class AuthorSchema(ma.ModelSchema)
    
    flask-marshmallow>=0.12.0 (recommended)
    class AuthorSchema(ma.SQLAlchemyAutoSchema)
"""

# 使用flask_marshmallow初始化model
class UserSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = User
        load_instance = True


"""

# 序列号方法2
from marshmallow import Schema, fields

# 使用marshmallow初始化model
class UserSchema(Schema):
    id = fields.Integer()
    name = fields.String()
    pwd = fields.String()

    class Meta:
        # 设置序列化字段
        fields = ["id", "name", "pwd"]
        # 转化为有序字典
        ordered = True

"""
4.2.3 route目录
4.2.3.1 interceptor.py
from flask import request
from dao.base_db.redis_db import redis_db


# 设置拦截器
def before_interceptor():
    # Pass white list
    if white_list():
        pass
    else:
        res_status = check_token()
        if res_status == 1:
            pass
        else:
            return res_status


# 设置白名单
def white_list():
    url_white_list = ["/flask/public/captcha", "/flask/public/login", "/flask/public/register", "/flask/public/initdb"]
    cur_url = request.path

    # Pass the url
    if cur_url in url_white_list:
        return True
    else:
        return False


# 设置token
def check_token():
    token = request.headers.get("token")
    if token is None:
        return "Token None"

    token_ttl = redis_db.ttl(token)

    # 验证码已经过期
    if token_ttl <= 0:
        return "Token expired"

    # 获取redis中的code
    redis_token = redis_db.get(token)

    if token != redis_token:
        return "Token error"

    return 1
4.2.3.2 operate_blueprint.py
# Configure Blueprint

from route.public_route import public_bp
from route.userinfo import userinfo_bp


class OperateBlueprint():

    # Init the app
    def __init__(self, app):
        self.__app = app
        self.__base_path = "/flask"

    # 初始化蓝本
    def init_blueprint(self):
        # Register the blueprint
        self.__app_register_blueprint(public_bp)
        self.__app_register_blueprint(userinfo_bp)

    # 在Flask中添加蓝本
    def __app_register_blueprint(self, blueprint):
        self.__app.register_blueprint(blueprint, url_prefix=self.__base_path + blueprint.name)
4.2.3.3 public_route.py
from flask import Blueprint, jsonify, request
from service.public_service import register_user, login_user, generate_captcha, create_table


public_bp = Blueprint("/public", __name__)


@public_bp.route("/captcha", methods=['POST'])
def captcha():
    captcha_dict = generate_captcha()
    return jsonify(captcha_dict)


@public_bp.route("/login", methods=['POST'])
def login():
    # 获取json数据
    data = request.get_json()
    print(data)
    res = login_user(data['name'], data['pwd'], data['code_key'], data['code'])
    return jsonify(res)


@public_bp.route("/register", methods=['POST'])
def register():
    register_user()
    return "register"


@public_bp.route("/initdb", methods=['POST'])
def init_mysql_db():
    return create_table()
4.2.3.4 userinfo.py
from flask import Blueprint
userinfo_bp = Blueprint("/userinfo", __name__)


@userinfo_bp.route("/info", methods=['POST'])
def login():
    return "Mason"
4.2.4 service目录

public_service.py

from dao.base_db.redis_db import redis_db
from dao.base_db.mysql_db import mysql_db, init_table

from dao.mysql_dao.model.user_model import User
from dao.mysql_dao.schema.user_schema import UserSchema

from util.operate_captcha import operate_captcha
from util.operate_token import operate_token


def generate_captcha():
    # 生成验证码
    code = operate_captcha.generate_code()
    # 生成图片验证码
    image_base64_str = operate_captcha.generate_captcha_base64(code)

    # 生成唯一key
    code_key = operate_captcha.generate_code_key()

    # 存入Redis
    redis_db.set(code_key, code.casefold(), 30)

    data = {
        "code_key": code_key,
        "code_img": image_base64_str
    }

    return data


def register_user():
    user = User()
    user.name = "mason"
    user.pwd = "123456"

    # 添加数据
    mysql_db.session.add(user)
    mysql_db.session.commit()


def login_user(name, pwd, code_key, code):

    code_ttl = redis_db.ttl(code_key)

    # 验证码已经过期
    if code_ttl <= 0:
        return -1

    # 获取redis中的code
    redis_code = redis_db.get(code_key)

    # 验证码过期
    if redis_code != code.casefold():
        return -2

    # 查询数据
    user = User.query.filter_by(name=name, pwd=pwd).first()

    # 序列号对象
    user_json = UserSchema().dump(user)
    print(user_json)

    # 生成token
    token = operate_token.create_token(user.id, user.name, 60)

    # 添加到redis
    redis_db.set(token, token, 60)

    return token


def create_table():
    init_table()
    return "create table"
4.2.5 util目录
4.2.5.1 operate_captcha.py
from captcha.image import ImageCaptcha
import random

import base64
import uuid


class OperateCaptcha:

    def generate_code(self, code_len=4):
        code_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
        chars_len = len(code_chars) - 1
        code = ''
        for _ in range(code_len):
            index = random.randint(0, chars_len)
            code = code + code_chars[index]
        return code

    def generate_captcha_base64(self, code):
        # 生成验证码
        image = ImageCaptcha()

        # 生成图片BytesIO
        img_bytes_io = image.generate(code)
        # 转化为字符串
        image_base64 = base64.b64encode(img_bytes_io.read())
        image_base64_str = "data:image/png;base64," + str(image_base64, 'utf-8')
        return image_base64_str

    def generate_code_key(self):
        # 生成唯一标识
        code_key = str(uuid.uuid1())
        return code_key


operate_captcha = OperateCaptcha()

4.2.5.2 operate_token.py
import jwt
from datetime import datetime, timedelta


# 操作Token
class OperateToken:

    def __init__(self):
        self._private_key = "123456"
        pass

    # 创建token
    def create_token(self, user_id, user_name, expiry_seconds):
        # Calculate expiry time
        expiry_time = datetime.utcnow() + timedelta(seconds=expiry_seconds)

        payload = {
            'exp': expiry_time,
            'user_id': user_id,
            'username': user_name
        }

        # 加密
        encode_jwt = jwt.encode(payload, self._private_key, algorithm='HS256')
        return encode_jwt

    # 验证token
    def check_token(self, token):
        decode_jwt = "-1"
        # 解密
        try:
            decode_jwt = jwt.decode(token, self._private_key, algorithms=['HS256'])
        except jwt.PyJWTError:
            print("Token is error!")
        return decode_jwt


operate_token = OperateToken()

5 postman截图

5.1 初始化数据表
http://127.0.0.1:5000/flask/public/initdb

5.2 注册接口
http://127.0.0.1:5000/flask/public/register

在这里插入图片描述

5.3 调用info接口

调用权限口需要验证token

http://127.0.0.1:5000/flask/userinfo/info

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flask简单调用Redis、MySQL和生成token及token验证 的相关文章

随机推荐

  • 使用raspberry pi pico 制作红绿灯

    需要的东西 一块面包版 一块raspberry pi pico 红绿黄led灯各一颗 220欧电阻3只 若干线 编程软件 thonny 操作系统 deepin 23 结果展示 使用raspberry pi pico 制作红绿灯 from m
  • 金山云服务器异常,金山云-文档中心-金山云告诉你:找不到服务器或dns错误怎么办...

    我们在用电脑 会经常使用浏览器 不少人经常在浏览网页时候突然跳出一个提示 上面显示 找不到服器 或 dns错误 下面 给大家分享找不到服务器或dns错误的解决经验 1 病毒所致 如果你电脑中了病毒 让你的DNS被劫持 比如自己的浏览器主页被
  • 【毕业设计】基于PLC的十字路口交通灯控制系统设计【仿真+源码+论文】

    摘 要 本次设计的课题是基于PLC的十字路口交通灯控制系统设计 传统的十字路口交通灯多采用单片机集成电路作为控制系统 单片机系统虽然在功能上能够实现十字路口交通灯的各种控制需求 但是单片机控制系统在设计时需要数字电路与模拟电路的完美结合 这
  • 基于跳表实现的轻量级KV存储引擎 项目总结

    参考 https github com youngyangyang04 Skiplist CPP 项目介绍 KV存储引擎 众所周知 非关系型数据库redis 以及levedb rockdb其核心存储引擎的数据结构就是跳表 本项目就是基于跳表
  • 5.0 Vue中使用webpack

    文章目录 webpack的基本使用 webpack中的插件 webpack打包发布 Source Map 注意 在实际开发中我们并不需要自己配置 webpack webpack中 的用法 在Chrome浏览器中安装vue devtools调
  • QT书籍分享——最全资料汇总

    QT从入门到精通 学习路线 市面上QT学习的书籍也挺多的 今天从学习路径上给大家一一盘点一下 并附上相关链接 大家可以根据需求下载哦 1 语言基础学习 学习QT最最最基础的当然是语言学习了 可以选择C 语言 也可以选择Python语言 C
  • 佛祖保佑,永无bug——springboot项目启动图案的修改方法

    在resources目录 与application yml文件同级目录 下创建banner txt文件 将下面的代码复制进去就好了 AnsiColor BRIGHT YELLOW ooOoo o8888888o
  • 动态规划-各种题型及思路整理(自用笔记,大神绕道)

    目录 简介 分类 基本思想 基本思路 状态转移方程 适用条件 一句话总结 应用 前缀和思想 简介 动态规划 dynamic programming 简称dp 是运筹学的一个分支 是求解决策过程 decision process 最优化的数学
  • 21天学习挑战赛——Python操作MySQL和SqlServer

    目录 1 pymysql模块 2 pymysql模块使用说明 2 1 pymysql操作流程图 2 2 创建连接对象 2 3 获取游标对象 2 4 用法举例 2 4 1 获取一条数据 6 4 2 获取多条数据 6 4 3 对数据进行增删改操
  • 未来社交媒体的变革者

    近日 Meta宣布了其认可的七大社交媒体趋势 这些趋势代表了未来社交媒体发展的核心方向 这些趋势中 生成式AI AR VR营销等引人注目的技术入选 预示着我们即将迎来全新的社交媒体时代 一 生成式AI 像人一样理解并回应 近年来 生成式AI
  • linux 非root用户 安装pyscipopt

    前提 实验室的服务器 我没有root权限 1 尝试用conda方法onda install channel conda forge pyscipopt 出现未知错误 搜遍百度谷歌stackoverflow都没有找到有人和我一样的问题 不知道
  • 基于Java的贪吃蛇小游戏

    一 开发思路 设定一个一定大小的且大小不可变的游戏窗口 在创建的窗口上绘制游戏的基本面板样式 使用提前保存的素材图标绘制一条静态的小蛇 使小蛇能够移动 实际只需蛇头坐标移动 每节身体覆盖前一节身体坐标 设置定时器Timer timer ne
  • Java的异常处理机制

    一 什么是java异常 java异常指在程序运行时可能出现的一些错误 如 文件找不到 网络连接失败 非法参数等 异常是一个事件 它发生在程序运行期间 中断了正在执行的程序的正常指令流 Java通过API中Throwable类的众多子类描述各
  • C# SuperSocket 手把手教你入门 傻瓜教程---9(CountSpliterReceiveFilter - 固定数量分隔符协议)使用COMMAND

    C SuperSocket 手把手教你入门 傻瓜教程系列教程 C SuperSocket 手把手教你入门 傻瓜教程 1 服务器单向接收客户端发送数据 C SuperSocket 手把手教你入门 傻瓜教程 2 服务器和客户端双向通信 C Su
  • Linux服务器wget:unable to resolve host address解决方法

    Linux服务器wget unable to resolve host address解决方法 问题 今天使用虚拟机安装linux系统镜像使用的是CentOS 在一切都准备好的时候 想要去安装Redis时碰到了wget unable to
  • 自定义九宫格控件NineGridLayout ,实现微信朋友圈图片九宫格显示

    前言 很多时候我们都在刷微博或者微信朋友圈的时候都会看到很多图片 而这些图片的显示跟我们平时很多控件的显示方式都不一样 而且 当我们仔细去观察后就会发现 他加载的图片都是根据图片数量动态加载的 根据不同的图片数量来用不同的布局显示 如下图
  • 硬件防火墙和软件防火墙的区别有哪些?

    什么是防火墙 防火墙 指由软件和硬件设备组合而成 在内部网和外部网之间 局域网与外网之间的保护屏障 就像架起了一面墙 它能使网络之间建立起一个安全网关 从而保护内部网免受非法用户的侵入 熟悉互联网的朋友一定对防火墙不陌生 不管是电脑自带的防
  • OBJ格式简单用法

    参考 https www cnblogs com hont p 5239725 html https zhuanlan zhihu com p 342244212 http zwqxin com archives opengl obj mo
  • ceph-deploy命令应用

    记录 336 场景 在CentOS 7 9操作系统上 使用ceph deploy创建ceph集群 部署集群的mon mgr mds osd rgw等组件 版本 操作系统 CentOS 7 9 ceph版本 ceph 13 2 10 名词 c
  • Flask简单调用Redis、MySQL和生成token及token验证

    项目地址 https github com MasonYyp myflask 1 安装python基础环境 安装flask pip install flask 安装redis pip install redis 安装操作MySQL的包 pi