«

pyjwt中,假如修改这个token的荷载中的exp值,再生成荷载,那jwt能否检测到的实验

qkabcd 发布于 阅读:398 IT技术


JWT(JSON Web Token)的签名机制确保了令牌的完整性和真实性。如果你修改了 JWT 的荷载(payload)中的 exp 值或其他任何字段,然后尝试使用原始的签名,JWT 的验证将失败,因为签名不再匹配修改后的荷载。

示例:验证修改后的 JWT

假设你有一个原始的 JWT 令牌:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDg1MDc0fQ.your_signature_here

如果你修改了荷载中的 exp 值,例如将其改为 1743086137,新的荷载部分将变为:

eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDg2MTM3fQ

如果你尝试将修改后的荷载与原始签名组合成一个新的令牌:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDg2MTM3fQ.your_signature_here

这个令牌将无法通过验证,因为签名部分不再匹配荷载部分。

Python 验证代码

以下是使用 Python 的 PyJWT 库验证 JWT 的示例代码:

import jwt

# JWT 配置
SECRET_KEY = "your-secret-key"  # 替换为你的密钥
ALGORITHM = "HS256"

# 示例:验证 JWT 签名
def verify_jwt(token: str):
    try:
        # 解码并验证 JWT 签名
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload
    except jwt.ExpiredSignatureError:
        print("Token has expired")
        return None
    except jwt.InvalidTokenError:
        print("Invalid token")
        return None

# 示例令牌(修改后的)
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDg2MTM3fQ.qUJTeL3QE487ozO-d6sJBhfQ19fcRNLW1KMqidEV7bo"

# 验证令牌
decoded_payload = verify_jwt(token)
if decoded_payload:
    print("Decoded payload:", decoded_payload)
else:
    print("Token verification failed")

输出结果

运行上述代码后,输出结果为:

Invalid token
Token verification failed

原因解释

  1. 签名不匹配

    • JWT 的签名部分是基于原始的荷载和头部生成的。如果你修改了荷载中的任何字段(如 exp),签名将不再有效。
  2. 验证失败

    • 在验证过程中,jwt.decode() 方法会重新计算签名并将其与令牌中的签名进行比较。如果两者不匹配,将抛出 InvalidTokenError 异常。

总结

JWT 的签名机制确保了令牌的完整性和真实性。任何对荷载或头部的修改都会导致签名不匹配,从而在验证时被检测到。这就是为什么即使你修改了 exp 值,JWT 也能检测到并拒绝验证的原因。

最后的实验结果

playload为:
{
"user_id": 123,
"username": "zhoucl",
"exp": 1743086137
}
经过pyjwt生成的token的playload:eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDg2MTM3fQ
完整token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDg2MTM3fQ.qUJTeL3QE487ozO-d6sJBhfQ19fcRNLW1KMqidEV7bo

仅仅修改playload中exp中的值:
{
"user_id": 123,
"username": "zhoucl",
"exp": 1743096137

}
替换中间playload:eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDk2MTM3fQ
但沿用原来的签名:qUJTeL3QE487ozO-d6sJBhfQ19fcRNLW1KMqidEV7bo
经过hack后的token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDk2MTM3fQ.qUJTeL3QE487ozO-d6sJBhfQ19fcRNLW1KMqidEV7bo

pyjwt正常加密hack的playload的token值:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDk2MTM3fQ.lNzt3YebtF-TpviYvyTK0396V-5hIeNZD9FIB2SR_Ps
签名为:lNzt3YebtF-TpviYvyTK0396V-5hIeNZD9FIB2SR_Ps

总结:playload是否被修改,该算法是比对最后的签名值:
hack playload:eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDk2MTM3fQ
原来 playload:eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiemhvdWNsIiwiZXhwIjoxNzQzMDg2MTM3fQ

hack playload签名:lNzt3YebtF-TpviYvyTK0396V-5hIeNZD9FIB2SR_Ps
原来 playload签名:qUJTeL3QE487ozO-d6sJBhfQ19fcRNLW1KMqidEV7bo

python