【自学开发之旅】Flask-前后端联调-异常标准化返回(六)

2023-09-17 16:35:48

注册联调:

前端修改:
1.修改请求向后端的url地址
文件:env.development修改成VITE_API_TARGET_URL= http://127.0.0.1:9000/v1

登录:token验证

校验forms/user.py

from werkzeug.security import check_password_hash


# 登录校验
class Loginform(Form):
    username = StringField(validators=[DataRequired()])
    password = StringField(validators=[DataRequired(), Regexp(r'\w{6,18}', message="密码不符合要求")])

    def validate(self):
        super().validate()
        if self.errors:
            return False
        user = User.query.filter_by(username = self.username.data).first()
        if user and check_password_hash(user.password, self.password.data):
            return user
        else:
            raise ValidationError("验证失败!")

router/user/user.py

from libs.auth import create_token

# 登录视图
class LoginView(Resource):
    def post(self):
        data = request.json
        form = LoginForm(data = data)
        user = form.validate()
        if user:
            return generate_response(msg="login success!", code=0)
        else:
            return generate_response(msg="login fail!", code=1)


api.add_resource(LoginView, "/login")

在config里写好secretkey和过期时间

# 内部私钥
SECRET_KEY = "123456"
# 过期时间
EXPIRES_IN = "10"

libs/auth.py生成token函数放这里

from flask import current_app
from itsdangerous import TimedSerializer


# 生成token
def create_token(uid):
    # 生成token,第一个参数传入内部私钥,第二个参数有效期
    s = TimedSerializer(current_app.config["SECRET_KEY"], current_app.config["EXPIRES_IN"])
    token = s.dumps({"uid":uid})
    return token

在这里插入图片描述
每次请求的token都不一样

pyjwt是web开发里专门用来生成token的库
pip install pyjwt
libs/auth.py

import jwt
from jwt.exceptions import ExpiredSignatureError, InvalidSignatureError

#用jwt生成token库
def create_token(uid):
    expir_in = current_app.config.get("EXPIRES_IN")
    payload = {"uid":uid, "exp":time.time() + expir_in}
    print(payload)
    key = current_app.config["SECRET_KEY"]
    token = jwt.encode(payload, key)
    return token

过期时间改回整形config/settings.py

# 过期时间
EXPIRES_IN = 600

在这里插入图片描述
这个token是base64加密

{
    "code": 0,
    "msg": "login success!",
    "data": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjMsImV4cCI6MTY5NDkzMjIyOS4zNDM5MTF9.03zt-xxAvgJ487Hwfk3nyCa-vq0ml3kPcEo3SDT-UOc",
        "username": "jd2"
    }
}

Header
Payload
{“alg”:“HS256”,“typ”:“JWT”}{“uid”:3,“exp”:1694932229.343911}

Signature
为了得到签名部分,你必须有编码过的header、编码过的payload、一个秘钥,签名算法是header中指定的那个,然对它们签名即可。
例如:

HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret)

服务端验证:拿到token之后,按照里面的header+payload+服务端保存的secretkey一起进行相同算法加密。得到新的签名,再和客户端传递的签名比较,一致就验证通过

两种验证:api验证,token验证
#验证token
libs/auth.py

def auth_required(func):
    def inner(*args, **kwargs):
        api_flag = request.args.get("api")
        if (api_flag == "1" and api_auth()) or token_auth():
            return func(*args, **kwargs)
        else:
            return "认证失败"
    return inner


# 验证token
def token_auth():
    token = request.headers.get("token")
    if token:
        try:
            print(time.time())
            jwt_obj = jwt.decode(token, current_app.config.get("SECRET_KEY"),
                                 algorithms=["HS256"])
        except InvalidSignatureError as e:
            print("token不合法", e)
            return False
        except ExpiredSignatureError as e:
            print("token过期", e)
            return False
        return True
    else:
        return False

首先POST访问127.0.0.1:9000/v1/login
得到token,复制粘贴,然后GET访问127.0.0.1:9000/v1/product,HEADERS中代token字段访问
在这里插入图片描述
前后端联调

前端流程

异常标准化返回
libs/error_code.py

from werkzeug.exceptions import HTTPException

class APIException(HTTPException):
    code = 500   #http状态码
    message = "fail!"  #状态描述信息
    status_code = 9999 # 程序状态
    def __init__(self, message=None, code=None, status_code = None):
        if message:
            self.message = message
        if code:
            self.code = code
        if status_code:
            self.status_code = status_code
        super(APIException, self).__init__()
    def get_body(self, environ = None, scope = None) -> str:
        body = dict(
            message = self.message,
            code = self.status_code
        )
        import json
        content = json.dumps(body)
        return content

    def get_headers(self, environ = None, scope = None,) :
        return [('content-Type', 'application/json')]

#自定义异常类
class APIAuthorizedException(APIException):
    message = "API授权认证失败"
    status_code = 10002
    code = 401

class FormValidateException(APIException):
    message = "表单验证失败"
    status_code = 10003

class TokenFailException(APIException):
    message = "token不合法,验证失败"
    status_code = 10005
    code = 401

libs/handler.py

from flask_restful import HTTPException
from libs.error_code import APIException

#无论什么异常  都返回APIException
def default_error_handler(ex):
    if isinstance(ex, APIException):
        return ex
    if isinstance(ex, HTTPException):
        code = ex.code
        message = ex.description
        status_code = 10001
        return APIException(code = code, message=message, status_code=status_code)
    return APIException()
from libs.handler import default_error_handler

#异常标准化返回
api.handle_error = default_error_handler

#异常标准化返回
handle_error 原本处理异常情况返回的一个方法
当发生异常情况时,会自动调用handle_error函数处理异常返回
在这里插入图片描述
修改libs/auth.py

from libs.error_code import APIAuthorizedException

def auth_required(func):
    def inner(*args, **kwargs):
        api_flag = request.args.get("api")
        if (api_flag == "1" and api_auth()) or token_auth():
            return func(*args, **kwargs)
        else:
            raise APIAuthorizedException
    return inner

在这里插入图片描述

更多推荐

C语言生成随机数、C++11按分布生成随机数学习

C语言生成随机数如果只要产生随机数而不需要设定范围的话,只要用rand()就可以;rand()会返回一随机数值,范围在0至RAND_MAX间;RAND_MAX定义在stdlib.h,其值为2147483647;如果想要获取在一定范围内的数的话,直接做相应的除法取余即可;如何获取小数呢?例如,我们可以先获得10001以内

ELK日志分析系统+ELFK(Filebeat)

本章结构:1、ELK日志分析系统简介2、Elasticsearch介绍(简称ES)3、Logstash介绍4、Kibana介绍5、实验,ELK部署一、ELK日志分析系统简介ELK平台是一套完整的日志集中处理解决方案,将ElasticSearch、Logstash和Kiabana三个开源工具配合使用。可以提高安全性,集中

Ubuntu 20.04 安装 Franka Control Interface (FCI)

文章目录前言一、安装libfranka和franka_ros二、设置实时内核1.安装依赖2.编译内核3.安装内核4.验证内核三、在实时内核下安装显卡驱动1.切换回之前的内核2.切换至实时内核3.允许用户为其进程设置实时权限前言本文介绍在ubuntu20.04中安装FrankaControlInterface(FCI),

GAN里面什么时候用detach的说明

在生成对抗网络(GAN)中,生成器(G)和判别器(D)通常是两个独立的神经网络,它们之间会有梯度传播的互动。下面是一个简单的GAN的PyTorch实现,用于生成一维数据,以展示何时应该使用detach()。importtorchimporttorch.nnasnnimporttorch.optimasoptim#生成器

车辆检测:An Efficient Wide-Range Pseudo-3D Vehicle Detection Using A Single Camera

论文作者:ZhupengYe,YinqiLi,ZejianYuan作者单位:Xi'anJiaotongUniversity论文链接:http://arxiv.org/abs/2309.08369v1项目链接:https://www.youtube.com/watch?v=1gk1PmsQ5Q8内容简介:1)方向:车辆检

高并发场景下的接口调用优化

AI绘画关于SD,MJ,GPT,SDXL百科全书面试题分享点我直达2023Python面试题2023最新面试合集链接2023大厂面试题PDF面试题PDF版本java、python面试题项目实战:AI文本OCR识别最佳实践AIGamma一键生成PPT工具直达链接玩转cloudStudio在线编码神器玩转GPUAI绘画、A

网络安全(黑客)自学笔记

前言作为一个合格的网络安全工程师,应该做到攻守兼备,毕竟知己知彼,才能百战百胜。计算机各领域的知识水平决定你渗透水平的上限。【1】比如:你编程水平高,那你在代码审计的时候就会比别人强,写出的漏洞利用工具就会比别人的好用;【2】比如:你数据库知识水平高,那你在进行SQL注入攻击的时候,你就可以写出更多更好的SQL注入语句

数据字段保证唯一性

数据字段保证唯一性我们日常开发中,常见这么一个需求,要求一个code,一个name,需要保证code不重复,而code是用户输入的,常见的就比如一些字典等。这个的我们常见的几种做法的话。唯一键要么就是直接以code作为主键,这样的话,伪代码基本就是@Transactional(rollbackFor=Exception

在 Substance Painter中自定义Shader

为什么要学习在SubstancePainter中自定义Shader?答:需要实现引擎与SubstancePainter中的渲染效果一致,材质的配置也一致,所见即所得。基础概述首先在着色器设置这里,我们可以查看当前渲染使用的着色器如果没有着色器设置窗口,可以在窗口这里打开点击着色器名称,可以切换当前拥有的shader相应

沉降安全监测之静力水准仪安装与精度分析

静力水准仪的安装使用步骤如下:1、选择合适的安装位置:静力水准仪应该安装在平稳且不易受到外力影响的地面上,以确保测量结果的准确性。同时,应避免安装在有风的地方,因为风会影响水准仪的读数。2、安装支架:静力水准仪需要安装在支架上才能使用。支架应该牢固可靠,能够承受水平方向上的荷载。支架的高度应该与被测物体的高度相匹配,以

【2023研电赛】华东赛区一等奖:基于EtherCAT通信有限时间位置收敛伺服系统

本文为2023年第十八届中国研究生电子设计竞赛作品分享,参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来领!,分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来领!基于EtherCAT通信有限时间位置收敛伺服系统参赛单位:浙江工业大学指导老师:陈强吴春参赛队员:沙为民吴辰浩申屠方

热文推荐