码迷,mamicode.com
首页 > Web开发 > 详细

JWT(Json WEB Token)

时间:2019-03-25 01:15:22      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:start   datetime   adt   Fix   方法   序列化   ret   timestamp   方案   

JWT 简介

JWTJson WEB Token)是一种采用 Json 方式安装传输信息的方式。 JWT 有针对各种开发语言的库。 python 中使用的是 PyJWT,它是 PythonJWT 的实现。

JWT 应用场景

服务端往往需要一个 ID 来表示客户端的身份,可以使用 session ,也可以在服务端创建一个 ID 返回给客户端。但是,要保证客户端不可篡改。JWT 就可以实现这种需求。

  • JWT 是在服务端生成一个标识,并使用某种算法对标识签名。
  • 服务端收到客户端发来的标识,需要检查签名。
  • 这种方案的缺点是,加密、解密需要消耗 CPU 计算资源,无法让浏览器自己主动检查过期的数据以清除。
  • 这种方案的优点是,不需要在服务端存放大量的session,减少了对内存的压力。

  • 用于认证

    常应用于服务端认证接口的 session 方案 ,这是 Jwt 最常用的场景,一旦用户登录成功,就会得到 Jwt ,然后请求中就可以带上这个 Jwt 。服务器中 Jwt 验证通过,就可以被允许访问资源。甚至可以在不同域名中传递,在单点登录(Single Sign On)中应用广泛。

  • 用于数据交换

    Jwt 可以防止数据被篡改,它还可以使用公钥、私钥,确保请求的发送者是可信的

JWT 安装

pip install pyjwt

JWT 原理

可知 jwt 生成的 token 分为三部分

  1. header: 由数据类型、加密算法构成
  2. payload: 负载就是要传输的数据,一般来说放入python对象即可,会被 json 序列化
  3. signature: 签名部分。是前面2部分数据分别 base64 编码后 使用点号连接后,加密算法使用 key 计算好一个结果,再被 base64 编码,得到签名

所有数据都是明文传输的,只是做了 base64,如果是敏感信息,请不要使用 jwt
数据签名的目的不是为了隐藏数据,而是保证数据不被篡改。如果数据篡改了,发回到服务器端,服务器使
用自己的 key 再计算一遍,然后进行签名比对,一定对不上签名。

Base64URL

  • HeaderPayload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。
  • JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符 +/=,在 URL 里面有特殊含义,所以要被替换掉:= 被省略、+ 替换成 -/ 替换成 ***_*** 。这就是 Base64URL 算法。

JWT 使用

JWT 方法说明

方法 说明
jwt.encode(payload, key, algorithm=‘HS256‘, headers=None, json_encoder=None) 生成 jwt, bytes 类型的 base64 编码
jwt.decode(jwt, key=‘‘, verify=True, algorithms=None, options=None, **kwargs) 解码 jwt 为 bytes 类型的 json
jwt.get_unverified_header(jwt) 返回一个未验证的 jwt 头部信息

jwt.encode 参数说明

    def encode(self,
               payload,  # type: Union[Dict, bytes]
               key,  # type: str
               algorithm='HS256',  # type: str
               headers=None,  # type: Optional[Dict]
               json_encoder=None  # type: Optional[Callable]
               ):

jwt.decode 参数说明

    def decode(self,
               jwt,  # type: str
               key='',   # type: str
               verify=True,  # type: bool
               algorithms=None,  # type: List[str]
               options=None,  # type: Dict
               **kwargs):

jwt.get_unverified_header() 参数说明

    def get_unverified_header(self, jwt):
        """Returns back the JWT header parameters as a dict()

        Note: The signature is not verified so the header parameters
        should not be fully trusted until signature verification is complete
        """
        headers = self._load(jwt)[2]
        self._validate_headers(headers)

        return headers

jwt.encode() 方法使用

import jwt
password = '123456'
# 生成bytes类型的token
token = jwt.encode({"payload":'this is my payload'}, password, 'HS256')

print('    token:',token)
head, payload, signature = token.split(b'.')  # 将成成的token(是bytes类型)切割成三段: head, payload, signature
print('     head:',head)
print('  payload:',payload)
print('signature:',signature)
------------------------------结果--------------------------------------
    token: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXlsb2FkIjoidGhpcyBpcyBteSBwYXlsb2FkIn0.bPGtksZQ-ncY5mya0bF7EmpO82nlN1ohk9L2Dl2D4RA'
     head: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9'
  payload: b'eyJwYXlsb2FkIjoidGhpcyBpcyBteSBwYXlsb2FkIn0'
signature: b'bPGtksZQ-ncY5mya0bF7EmpO82nlN1ohk9L2Dl2D4RA'

jwt.decode() 方法使用

import jwt
import base64
password = '123456'
# 生成bytes类型的token
token = jwt.encode({"payload":'this is my payload'}, password, 'HS256')

# 此函数是为了避免转码时候 base64 编码结尾处缺少 b'=',而报错.
def addpad(x):
    suffix = 4 - len(x) % 4
    return x + b'=' * suffix

head, payload, signature = token.split(b'.')  # 将成成的token(是bytes类型)切割成三段: head, payload, signature

# 将 token (bytes 类型)转换为原来的类型
token_decode = jwt.decode(token, password, algorithms=['HS256'])
head_decode = base64.urlsafe_b64decode(addpad(head))
payload_decode = base64.urlsafe_b64decode(addpad(payload))
signature_decode = base64.urlsafe_b64decode(addpad(signature))

print('    token_decode:',token_decode, type(token_decode))
print('     head_decode:',head_decode, type(head_decode))
print('  payload_decode:',payload_decode, type(payload_decode))
print('signature_decode:',signature_decode, type(signature_decode))

------------------------------结果--------------------------------------
    token_decode: {'payload': 'this is my payload'} <class 'dict'>
     head_decode: b'{"typ":"JWT","alg":"HS256"}' <class 'bytes'>
  payload_decode: b'{"payload":"this is my payload"}' <class 'bytes'>
signature_decode: b'l\xf1\xad\x92\xc6P\xfaw\x18\xe6l\x9a\xd1\xb1{\x12jN\xf3i\xe57Z!\x93\xd2\xf6\x0e]\x83\xe1\x10' <class 'bytes'>

jwt.decode() 方法实现过期验证

import jwt
import datetime
import threading

event = threading.Event()

passwd = '123456'

token = jwt.encode({
    'a':'test',
    'exp': int(datetime.datetime.now().timestamp() + 5)
    }, passwd, 'HS256')

print(token)
print('===============================')
print('start at about:     ',int(datetime.datetime.now().timestamp()))
while True:
    if not event.wait(1):
        try:
            print(jwt.decode(token, passwd))
        except Exception as e:
            print(e)
            break

执行结果

b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhIjoidGVzdCIsImV4cCI6MTU1MzQ0MDc5OH0.jzwOxmsp3zqVTXi38hsmu8K7c47j4NV8nPxQe9cQ3E0'
===============================
start at about:      1553440793
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
Signature has expired

jwt.get_unverified_header(jwt) 方法使用

import jwt
password = '123456'
token = jwt.encode({"payload":'this is my payload'}, password, 'HS256')

print('     token:',token)
print('jwt_header:',jwt.get_unverified_header(token))
------------------------------结果--------------------------------------
     token: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXlsb2FkIjoidGhpcyBpcyBteSBwYXlsb2FkIn0.bPGtksZQ-ncY5mya0bF7EmpO82nlN1ohk9L2Dl2D4RA'
jwt_header: {'typ': 'JWT', 'alg': 'HS256'}

JWT(Json WEB Token)

标签:start   datetime   adt   Fix   方法   序列化   ret   timestamp   方案   

原文地址:https://www.cnblogs.com/shichangming/p/10591312.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!