首页 > 编程语言 >Python实现JWT的生成及验证

Python实现JWT的生成及验证

时间:2023-05-25 23:32:14浏览次数:48  
标签:验证 Python JWT token 密钥 signature print data

一、概述

       在 JWT 安全性总结 中提到了JWT的三个组成部分,包括header、claims以及signature,其中Signature是一个签名的部分,其计算方法为:HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret) ,即header的BASE64编码、点号、Clamis的BASE64编码以及将secret作为盐值,以前面申明的HASH算法进行计算,得到的一个值,该值具有不可逆性。本篇博客用Python实现一下JWT的具体生成及验证。

二、准备

     从www.jwt.io取一个JWT令牌,密码设置为hello,我们得到JWT为eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.ElsKKULlzGtesThefMuj2_a6KIY9L5i2zDrBLHV-e0M,这里注意signature部分,下面我们要通过代码实现计算,看得到的signature是否与网站上生成的一致。

Python实现JWT的生成及验证_BASE64

三、生成JWT

(一)自己通过Python代码实现

直接上代码:

#先将token放在这里,后面生成新的token后可以进行对比
tokenold = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.ElsKKULlzGtesThefMuj2_a6KIY9L5i2zDrBLHV-e0M"


header = {

  "alg": "HS256",

  "typ": "JWT"

}

payload = {

  "sub": "1234567890",

  "name": "John Doe",

  "iat": 1516239022

}

signature = ''

'''
  根据JWT生成的原理,通过代码实现JWT的生成以及验证
'''
'''
   JWT即Json Web Token,在JSON格式中通常为了格式化,在每个部分冒号(“:”)或者逗号(“,”)前后可能存在一些空格,这里需要先将无用的空格去掉,避免影响结果生成。
'''

def remove_spaces(token):
    token = json.dumps(token, separators=(',', ':'))
    return token
'''
    使用hmac模块的new方法,调用相应的函数,生成signature签名
    这里写一个方法,传入待签名的data以及签名的密钥key
   返回签名值

'''

def getSha256(data, key):
    key = key.encode("utf-8")
    data = data.encode("utf-8")
    sign = hmac.new(key, data, digestmod='sha256').digest()
    return sign

'''
根据JWT明文内容,进行JWT签名,并且生成完整的JWT
'''

def jwtGenerate1():
    '''
    1、对header/payload部分去掉多余的空格     2、进行BASE64编码,通过decode去掉结果中的"b"
    3、将结果中的等号去掉    

'''
   
headerBase64Encode = base64.b64encode(str(remove_spaces(header)).encode("utf-8")).decode().replace("=", "")
    payloadBase64Encode = base64.b64encode(str(remove_spaces(payload)).encode("utf-8")).decode().replace("=", "")
    # print(headerBase64Encode)
    '''
    4、将header的BASE64编码、点号、payload的BASE64编码组合,得到待签名的数据    

'''
    data = str(headerBase64Encode) + "." + str(payloadBase64Encode)
    # print("data: " + data)
    '''
    5、将准备好的data以及密钥值传入前面定义的函数getsha256
    6、将返回的结果进行BASE64编码,去掉其中的等号    

'''
    signature = str(base64.b64encode(getSha256(data, "hello")).decode()).replace("=", "")
    '''
    7、组合所有得到的BASE64编码,然后将其中的"/"以及“_"分别替换为"+"以及"-",得到最终的token值    

'''
    token = str(headerBase64Encode + "." + payloadBase64Encode + "." + signature).replace("/", "_").replace("+", "-")

    print("header: " + str(headerBase64Encode))
    print("payload: " + payloadBase64Encode)
    print("signature: " + signature)
    print("token: " + token)
    if tokenold == token:
        print("ok!")

运行一下看结果:

Python实现JWT的生成及验证_BASE64_02

Signature值为ElsKKULlzGtesThefMuj2_a6KIY9L5i2zDrBLHV-e0M,与网站上的一致。

(二)通过jwt模块实现

代码实现:

'''
 使用pyjwt库进行jwt 生成以及jwt的验证过程,该方法使用简单
'''

def jwtGenerate2():
    '''
    使用jwt的encode方法,直接生成token,key为签名密钥
    '''
    token = jwt.encode(payload=payload, key="hello", algorithm='HS256', headers=header)

    print(token)

运行得到结果:

Python实现JWT的生成及验证_BASE64_03

可以看到结果是一样的。

四、校验JWT

(一)自己通过Python代码实现

代码实现:

'''

根据JWT token进行解码,判断签名的解密是否正确

'''

def jwtCheck1():

    '''

    1、分别获取到BASE64编码后的header、payload、signature

    '''

    headerBase64Encode = tokenold.split(".")[0]

    payloadBase64Encode = tokenold.split(".")[1]

    signatureBase64Encode = tokenold.split(".")[2]

    '''

    2、将编码后的header、点号、payload组合,得到待签名的数据

    '''

    data = headerBase64Encode + "." + payloadBase64Encode


    '''

    3、传入签名密钥,对数据进行签名,得到signature的BASE64编码

    4、注意要将其中的“=”、“/”、“+”分别替换为无、“_”、“-”
这里我使用的密钥为hello

    '''

    signature = str(base64.b64encode(getSha256(data, "hello
")).decode()).replace("=", "").replace("/", "_").replace("+", "-")

    print("The new signature is: " + signature)

    print("The old signature is: " + signatureBase64Encode)

    '''

    5、将原始签名数据与自己计算得到的签名数据进行比较,如果相同,则签名密钥正确

    '''

    if signatureBase64Encode == signature:

        print("Signature Verified !")

    else:

        print("Signature Faied !")

运行得到结果:

Python实现JWT的生成及验证_BASE64_04

修改密钥为hao123再试一下:

signature = str(base64.b64encode(getSha256(data, "hao123")).decode()).replace("=", "").replace("/", "_").replace("+", "-")

结果:

Python实现JWT的生成及验证_Python_05

可以看到,密钥修改了,导致签名校验失败。

(二)通过jwt模块实现

代码如下:

def jwtCheck2():

    '''

    使用jwt的decode方法,传入密钥,如果密钥正确,则返回payload

    如果密钥不正确,抛出异常,签名验证失败

    '''

    try:

        signatureNew = jwt.decode(tokenold, "hao123", algorithms=['HS256'], verify=True)

        print(signatureNew)

    except Exception as e:

        print(e)

密钥为hao123时,校验失败:

Python实现JWT的生成及验证_jwt_06

密钥为hello时,校验成功:

Python实现JWT的生成及验证_Python_07

五、总结扩展

     上面描述了两种方式用于JWT的生成与校验,第一种方式是自身通过代码去实现,第二种方式是通过模块去实现,结果一样,不过第一种方式让我更加深刻理解了原理。

      既然实现了JWT的校验,那么只需要将密钥作为变量,通过循环即可实现JWT的暴破,这里就不再体现了。

标签:验证,Python,JWT,token,密钥,signature,print,data
From: https://blog.51cto.com/u_9652359/6351659

相关文章

  • Python求前后第n个月函数
    数据分析常用到:#求往后第n个月#monthstr格式:YYYY-MM##printnext_month("2023-05",1)#2023-06#printnext_month("2023-05",6)#2023-11#printnext_month("2023-05",8)#2024-01defnext_month(monthstr,n):yearnum=int(mont......
  • 基于FPGA的医学图像中值滤波verilog实现,包括testbench和MATLAB验证程序
    1.算法仿真效果matlab2022a/Vivado2019.2仿真结果如下:通过matlab产生带噪声医学图片:FPGA仿真:通过MATLAB读取FPGA的仿真数据,并显示滤波后图像:2.算法涉及理论知识概要中值滤波是一种非线性数字滤波器技术,经常用于去除图像或者其它信号中的噪声。这个设计思想就是检查输入信......
  • 如何在ubuntu下安装Vscode并且运行C语言文件或者python文件
    要想在ubuntu中编写并运行C语言或python文件,有两种方法,第一种是直接用vim编写(在我之前的文章中有详细介绍)可以点击如下链接:如何在ubuntu安装C语言环境-代师-博客园(cnblogs.com)如何在Ubuntu中编写Python代码并运行-代师-博客园(cnblogs.com) 今天我要说的是用专......
  • 基于FPGA的医学图像中值滤波verilog实现,包括testbench和MATLAB验证程序
    1.算法仿真效果matlab2022a/Vivado2019.2仿真结果如下: 通过matlab产生带噪声医学图片:   FPGA仿真:   通过MATLAB读取FPGA的仿真数据,并显示滤波后图像:   2.算法涉及理论知识概要       中值滤波是一种非线性数字滤波器技术,经常用于去除图像或......
  • python 发送微信消息
    python自动化,可以模拟键盘输入,因此,可以控制微信,发送消息,代码如下:1importsys2importpyautogui3importpyperclip4importtime5importconfigparser67"""8安装依赖:9pipinstallpyautoguipyperclippyinstaller1011打包成exe:12pyins......
  • python 格式化代码
    安装pre-commitsudoaptinstallpre-commit-yrepos:-repo:https://github.com/python/blackrev:23.3.0hooks:-id:blacklanguage_version:python3exclude:src/ratel/potargs:["--line-length","18......
  • python计算余弦相似性和汉明距离
    要使用矩阵相乘来计算7个二进制编码之间的余弦相似性,我们需要先将二进制编码转换为数值向量。对于每个二进制编码,我们可以将0映射为-1,将1映射为1,从而得到一个数值向量。然后,我们可以将这些数值向量表示为一个矩阵,并进行矩阵相乘来计算余弦相似性。以下是一个示例代码,使用Python和......
  • Python竖版大屏2 | 用pyecharts开发可视化的奇妙探索!
    目录1、SHINE主题2、LIGHT主题3、MACARONS主题4、INFOGRAPHIC主题5、WALDEN主题6、WESTEROS主题7、WHITE主题8、WONDERLAND主题你好!我是@马哥python说,一名10年程序猿,正在试错用pyecharts开发可视化大屏的非常规排版。以下,我用8种ThemeType展示的同一个可视化数据大屏,可视化主题......
  • python试题
    1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20. 程序题1    程序题2     附加题        一、选择题每题4分1.关于二进制,八进制,十进制,十六进制的表示方......
  • Python集合 (set) 的增删改查及 copy()方法
    集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的。以下是集合最重要的两点:1、去重,把一个列表变成集合,就自动去重了。2、关系测试,测试两组数据之前的交集、差集、并集等关系。一、集合的创建set1=set({1,2......