flask 之JWT认证实现

news2024/10/5 13:04:22

目录

1、JWT

1.1、JWT概述

1.2、token的生成

1.3、token校验

1.4、flask项目中实现JWT认证

1、JWT

1.1、JWT概述

JWT(JSON Web Token)是一种用于身份验证和授权的开放标准。它由三部分组成,分别是头部、负载和签名。

头部(Header)是一个 JSON 对象,描述了使用的算法和类型。它通常包含两个字段:算法(alg)和类型(typ)。

负载(Payload)也是一个 JSON 对象,用于存储用户的相关信息。它可以包含一些预定义的字段,如过期时间(exp)、发布时间(iat)等,也可以包含一些自定义字段。

签名(Signature)使用指定的算法对头部和负载进行加密,生成一段字符串。这个字符串可以用于验证数据的完整性。

1、传统的token认证流程

  1. 用户登录:用户输入用户名和密码,向服务器发送登录请求。
  2. 生成token:服务器验证用户名和密码的正确性,如果验证通过,则生成一个随机字符串作为token,并将这个token与用户ID等关键信息关联起来(例如,将token和用户ID作为键值对存储在Redis等缓存中)。
  3. 返回token:服务器将生成的token返回给客户端,客户端将token保存在cookie或localStorage中。
  4. 携带token:当客户端需要访问需要认证的接口时,会在请求头中携带这个token。
  5. 验证token:服务器在接收到请求后,会从请求头中提取token,并根据token在缓存中查找对应的用户信息。如果找到了对应的用户信息,则说明用户已经登录且token有效;否则,说明用户未登录或token已过期。

2、传统token认证流程和JWT的对比

  1. 存储方式:传统token方式需要将token保存在服务器端(如Redis),而JWT则将token的所有信息都包含在token本身中,无需在服务器端保存。
  2. 安全性:JWT通过签名机制来确保数据的完整性和防止篡改,而传统token方式则更依赖于服务器端的验证。
  3. 应用场景:JWT更适用于分布式系统或跨域请求的场景,而传统token方式则更适用于传统的Web应用。

1.2、token的生成

jwt的生成token格式如下,即:由 . 连接的三段字符串组成。

eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ1c2VybmFtZSI6ImxqIiwiZXhwIjoxNzE2NzkyODI4fQ.WrT1XY8CC1vFo8tPpt0ZrDjje5ooD8hTOvIW42Z2WEo

1、生成规则如下:

  • token组成:将三段字符串通过 . 拼接起来就生成了jwt的token。
  • 第一段HEADER部分,固定包含算法和token类型,对此json进行base64url加密,这就是token的第一段。
headers = {
    'typ': 'jwt',
    'alg': 'HS256'
}
  • 第二段PAYLOAD部分,包含一些数据,对此PAYLOAD进行base64url加密,这就是token的第二段
payload = {
    'user_id':1,
    'username':'张三', 
    'role':'admin',
    'exp': "XXX"
    ...........
}
  • 第三段SIGNATURE部分,把前两段的base密文通过.拼接起来,然后对其进行HS256加密,再然后对hs256密文进行base64url加密,最终得到token的第三段。
base64url(
    HMACSHA256(
      base64UrlEncode(headers) + "." + base64UrlEncode(payload),
      secret # 秘钥加盐
    )
)

注意:base64url加密是先做base64加密,然后再把 - 替换 + _ 替换 / 。

2、代码实现:

  • 使用的库是:pyjwt模块。
  • 安装库:

pip install pyjwt

代码实现:

import jwt
import datetime

# 秘钥加盐
SALT = 'adasfasfgthfafklsaj?lkasld;)(hjasgbsvbfjh='

def create_token():
    # header
    headers = {
        'typ': 'jwt',
        'alg': 'HS256'
    }
    # payload
    payload = {
        'user_id': 1,  # 自定义用户ID
        'username': '张三',  # 自定义用户名
        'role': "admin", # 自定义角色
        'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2)  # 过期时间(2个小时)
    }
    result = jwt.encode(headers=headers, payload=payload, key=SALT, algorithm=["HS256"])
    return result

if __name__ == '__main__':
    token = create_token()
    print(token)

1.3、token校验

获取token之后,会按照以下步骤(主要是进行超时和合法性校验)进行校验:

  • 将token分割成 header_segment、payload_segment、crypto_segment 三部分
  • 对第一部分header_segment进行base64url解密,得到header
  • 对第二部分payload_segment进行base64url解密,得到payload
  • 对第三部分crypto_segment进行base64url解密,得到signature后进行合法性校验。
    • 拼接前两段密文,即:signing_input
    • 从第一段明文中获取加密算法,默认:HS256
    • 使用 算法+盐 对signing_input 进行加密,将得到的结果和signature密文进行比较。

代码实现:

import jwt

# 秘钥加盐
SALT = 'adasfasfgthfafklsaj?lkasld;)(hjasgbsvbfjh='

def get_payload(token):
    try:
        # 校验token合法性和是否超时
        verified_payload = jwt.decode(jwt=token, key=SALT, verify=True, algorithms=["HS256"])
        return verified_payload
    except jwt.ExpiredSignatureError:
        print("token已过期")
    except jwt.DecodeError:
        print('token认证失败')
    except jwt.InvalidTokenError:
        print('非法的token')

if __name__ == '__main__':
    token = "eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Ilx1NWYyMFx1NGUwOSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzQwMDIwMn0.iXqTAykKdA8ln0WMCsdhcc3Je0l4qOvYoxctkjEmhHs"
    payload = get_payload(token)
    print(payload)

1.4、flask项目中实现JWT认证

项目的目录结构如下:

1、app.py文件

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import base64
from flask import Flask, request, jsonify, g
from utils.jwt_auth import create_token, check_token

app = Flask(__name__)

# 通过url传递token
# 每一个请求前都进行token的验证
# @app.before_request
# def jwt_query_params_auth():
#     if request.path == '/login/':
#         return
#     token = request.args.get('token')
#     result = check_token(token)
#     if not result['status']:
#         return jsonify(result)
#     g.user_info = result['info']


# 通过Authorization请求头传递token


@app.before_request
def jwt_authorization_auth():
    if request.path == '/login/':
        return
    # 在实际项目中Authorization的组成一般是: Bearer toekn
    authorization = request.headers.get('Authorization', '')
    token = ""
    # 对head进行解密
    if authorization:
        # 获取token信息
        token = authorization.split(" ")[1]
        # 获取token中的header加密部分
        encoded_header = token.split(".")[0]
        # 注意:我们需要替换字符并确保字符串长度是 4 的倍数
        padded = encoded_header + '=' * (-len(encoded_header) % 4)
        # 对header进行base64url解密
        header = base64.urlsafe_b64decode(padded.replace('-', '+').replace('_', '/')).decode('utf-8')
        print(header)

    result = check_token(token)
    if not result['status']:
        return jsonify(result)
    g.user_info = result['info']



@app.route('/login/', methods=['POST'])
def login():
    user = request.form.get('username')
    pwd = request.form.get('password')
    print(user)
    # 检测用户和密码是否正确,此处可以在数据进行校验。
    if user == '张三' and pwd == '123456':
        # 用户名和密码正确,给用户生成token并返回
        token = create_token({'user_id':1, 'username':'张三', 'role':'admin'})
        return jsonify({'status': True, 'token': token})
    return jsonify({'status': False, 'error': '用户名或密码错误!'})


@app.route('/info/')
def order():
    print(g.user_info)
    return jsonify(g.user_info)


if __name__ == '__main__':
    app.run(debug=True)

2、jwt_auth.py文件

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import jwt
import datetime

# 秘钥加盐
SALT = 'adasfasfgthfafklsaj?lkasld;)(hjasgbsvbfjh='

def create_token(payload, timeout=60):
    """
    :function: 创建token
    :param payload:  例如:{'user_id':1,'username':'张三', 'role':'admin'}用户信息
    :param timeout: token的过期时间,默认60分钟
    :return:
    """
    headers = {
        'typ': 'jwt',
        'alg': 'HS256'
    }
    payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
    result = jwt.encode(headers=headers, payload=payload, key=SALT, algorithm="HS256")
    return result


def check_token(token):
    """
    :function: 检验token的合法性和是否过期
    :param token: 用户token信息
    :return: 返回检验结果
    """
    result = {'status': False, 'info': None, 'msg': None}
    try:
        print(token)
        verified_payload = jwt.decode(jwt=token, key=SALT, verify=True, algorithms=["HS256"])
        result['status'] = True
        result['info'] = verified_payload
    except jwt.ExpiredSignatureError:
        result['msg'] = 'token已失效'
    except jwt.DecodeError:
        result['msg'] = 'token认证失败'
    except jwt.InvalidTokenError:
        result['msg'] = '非法的token'
    return result

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1795138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第三方软件测试机构与CMA、CNAS资质

第三方软件测试机构 随着信息技术的快速发展,软件在各个领域的应用越来越广泛,软件的质量和安全性成为人们关注的焦点。为了确保软件的质量和安全性,第三方软件测试机构和CMA、CNAS资质成为了重要的保障。 第三方软件测试机构是独立于软件开…

python调用excel的demo

在本地安装Pycharm之后,新建工程,在main.py中键入如下代码,即可实现Python调用excel: import pandas as pd sheet pd.read_excel(test.xlsx) data sheet.loc[0].values print("读取指定行的数据:\n{0}".format(data)) 第一次编…

如何将 MySQL 数据库共享给他人?

文章目录 共享所有数据库给他人1. 连接到 MySQL 数据库2. 选择要使用的数据库3. 修改连接所需的 host4. 刷新权限 共享部分数据库给他人1. 创建用户2. 授权3. 刷新权限 结语 🎉欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是I…

JVMの静、动态绑定异常捕获JIT即时编译

在说明静态绑定和动态绑定之前,我们首先要了解在字节码指令的层面,JVM是如何调用方法的: 例如我有以下的代码,很简单就是在main方法中调用了另一个静态方法: public class MethodTest {public static void main(Strin…

git clone 文件名中文、有冒号等问题 fatal: repository ‘***/r/鏍″洯鏅烘収椋熷爞/.git/‘ not found

记录一个git问题,比较有意思,也比较难找。 背景 首先把代码拉下来,发现给我报错。 怀疑 刚开始以为是仓库地址变了,但是发现仓库地址并没有变过。 交流 然后寻找解决方案。因为同事也遇到过,同事交了我一招&…

数据结构第三篇【链表的相关知识点一及在线OJ习题】

数据结构第三篇【链表的相关知识点一及在线OJ习题】 链表链表的实现链表OJ习题顺序表和链表的区别和联系 本文章主要讲解关于链表的相关知识,喜欢的可以三连喔 😀😃😄😄😊😊🙃&#…

【iOS】——Runtime学习

文章目录 一、Runtime介绍二、Runtime消息传递三、实例对象、类对象、元类对象四、isa_t结构体的具体实现五、cache_t的具体实现六、class_data_bits_t的具体实现七、Runtime消息转发动态方法解析备用接收者完整消息转发 一、Runtime介绍 iOS的Runtime,通常称为Obj…

GitHub飙升!京东认证的“Python编程入门三剑客”究竟好在哪?

Python凭借着简单易学、功能强大,已经跃居TIOB编程语言榜首,并且已经开始了它的霸榜之旅。如何选择一套适合自己的Python学习教程,是每个Python爱好者面临的首要问题。 今天给小伙伴们带来的是图灵&京东认证的“Python编程入门三剑客”&…

项目:仿RabbitMQ实现的消息队列组件

文章目录 写在前面开源仓库和项目上线其他文档说明 需求分析BrokerServer交换机类型持久化消息应答 模块划分服务端模块客户端模块交换机数据管理模块队列数据管理模块绑定数据管理模块消息数据管理模块队列信息管理模块虚拟机数据管理模块路由匹配模块消费者管理模块信道管理模…

gomail发送邮件的参数如何设置?如何使用?

gomail发送邮件的认证方式有哪些?怎么设置邮件发信? Gomail是一个常用的Go语言邮件发送库,它提供了简单易用的接口,使得邮件发送变得非常方便。AokSend将详细介绍如何设置gomail发送邮件的参数,帮助开发者更好地理解和…

Java实现经纬度坐标转换

一、坐标系统简介 坐标系统,是描述物质存在的空间位置(坐标)的参照系,通过定义特定基准及其参数形式来实现。 坐标是描述位置的一组数值,按坐标的维度一般分为一维坐标(公路里程碑)和二维坐标…

申请HTTPS证书的具体步骤是什么?

在当今数字化时代,网络安全已成为企业和个人关注的焦点。HTTPS证书作为网络安全的重要组成部分,不仅象征着网站的安全性,更是数据保护和用户信任的基石。本文将详细阐述HTTPS证书的重要性以及如何申请和配置HTTPS证书,以帮助网站所…

24、Linux网络端口

Linux网络端口 1、查看网络接口信息ifconfig ens33 eth0 文件 ifconfig 当前设备正在工作的网卡,启动的设备。 ifconfig -a 查看所有的网络设备。 ifconfig ens33 查看指定网卡设备。 ifconfig ens33 up/down 对指定网卡设备进行开关 基于物理网卡设备虚拟的…

CSS 常用的三种居中定位布局

嗨,我是小路。今天主要和大家分享的主题是“”。 一、三种常用布局 1.子绝父相 margin 居中 注意:父级相对定位,子级绝对定位,并且子级margin-left,margin-top是负值,为宽度、高度的一半。 /** …

IDEA 2022

介绍 【尚硅谷IDEA安装idea实战教程(百万播放,新版来袭)】 jetbrains 中文官网 IDEA 官网 IDEA 从 IDEA 2022.1 版本开始支持 JDK 17,也就是说如果想要使用 JDK 17,那么就要下载 IDEA 2022.1 或之后的版本。 公司…

利用opencv-python实现图像全景拼接技术实现

这个代码的主要功能是将多张图像拼接成一张全景图。它使用了OpenCV库中的SIFT特征提取、特征匹配和图像变换等技术来实现图像拼接。 一、预览效果 二、安装依赖 contourpy1.2.1 cycler0.12.1 fonttools4.53.0 importlib_resources6.4.0 kiwisolver1.4.5 matplotlib3.9.0 numpy…

Linux中安装Docker,并使用Docker安装MySQL和Redis

1、安装docker 1卸载系统之前的docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine2、安装Docker-CE #安装必须的依赖 sudo yum install -y yum-utils \device-map…

12. MySQL 日志

文章目录 【 1. 日志的基本原理 】【 2. 错误日志 Error Log 】2.1 启动和设置错误日志2.2 查看错误日志2.3 删除错误日志 【 3. 二进制日志 Binary Log 】3.1 启动和设置二进制日志3.2 查看二进制日志3.3 删除二进制文件删除所有二进制日志删除小于指定编号的二进制日志删除创…

浅谈SpringBoot日志文件

文章目录 一、日志的作用二、如何在SpringBoot中使用日志2.1、在程序中得到日志对象。2.2、通过日志对象中提供的内置方法操打印日志信息2.2.1 日志级别2.2.1.1、日志级别有什么作用??2.2.1.2、日志级别的分类2.2.1.2、在配置文件中设置日志级别[!] 三、…

数字人动作解决方案,塑造逼真动作

在品牌形象塑造、市场推广及客户服务等领域,企业正面临着前所未有的挑战和机遇。为满足企业的需求,美摄科技凭借其在人工智能和计算机视觉领域的深厚积累,推出了面向企业的数字人动作解决方案,助力企业轻松打造逼真、灵活的虚拟形…