pyJWT

Posted zzy-9318

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pyJWT相关的知识,希望对你有一定的参考价值。

现在用JWT 非对称加密太火了,怎么能不跟上潮流?否则销售都不好意思出去吹牛逼!

PyJWT是一个Python库,用来编码/解码JWT(JSON Web Token)的

1.定义:根据维基百科的定义,JSON WEB Token(JWT,读作 [/d??t/]),是一种基于JSON的、用于在网络上声明某种主张的令牌(token)。JWT通常由三部分组成: 头信息(header), 消息体(payload)和签名(signature)。

1.1头信息指定了该JWT使用的签名算法:

header = {"alg":"HS256","typ":"JWT"}

1.2消息体包含了JWT的意图:

payload = {"loggedInAs":"admin","iat":1422779638}//iat表示令牌生成的时间  

1.3未签名的令牌由base64url编码的头信息和消息体拼接而成(使用"."分隔),签名则通过私有的key计算而成

key = secretkey  
unsignedToken = encodeBase64(header) + . + encodeBase64(payload)  
signature = HMAC-SHA256(key, unsignedToken) 

2.上代码:摘自https://www.cnblogs.com/liufei1983/p/8546505.html  写都不错,挺清晰的借鉴一下,不过项目里一般都是封装成装饰器,作为接口认证

技术分享图片
import datetime, jwt, time
from app.dao.userDao import UserDao
from flask import jsonify
from .. import common
class Auth():
    @staticmethod
    def encode_auth_token(user_id, login_time):
        """
        生成认证Token
        :param user_id: int
        :param login_time: int(timestamp)
        :return: string
        """
        try:
            payload = {
                exp: datetime.datetime.utcnow() + datetime.timedelta(days=0, seconds=10),
                iat: datetime.datetime.utcnow(),
                iss: ken,
                data: {
                    id:user_id,
                    login_time: login_time
                }
            }
            return jwt.encode(
                payload,
                secret,
                algorithm=HS256
            )
        except Exception  as e:
            return e

    @staticmethod
    def decode_auth_token(auth_token):
        """
        验证Token
        :param auth_token:
        :return: integer|string
        """
        try:
            payload = jwt.decode(auth_token, secret, options= {verify_exp:False})
            if (data in payload and id in payload[data]):
                return payload
            else:
                raise jwt.InvalidTokenError

        except jwt.ExpiredSignatureError:
            return "Token过期"
        except jwt.InvalidTokenError:
            return "无效的Token"

    def authenticate(self, username, password):
        """
        用户登录,登录成功返回token,写将登录时间写入数据库;登录失败返回失败原因
        :param password:
        :return: json
        """
        userDao = UserDao()
        user = userDao.search(username)
        if (user is None):
            return jsonify(common.falseReturn(‘‘, 找不到用户))
        else:
            if (user.password == password):
                login_time = int(time.time())
                token = self.encode_auth_token(user.username, login_time)
                return jsonify(common.trueReturn(token.decode(), 登陆成功))
            else:
                return jsonify(common.falseReturn(‘‘, 密码不正确))

    def identify(self, request):
        """
        用户鉴权
        :return: list
        """
        auth_header = request.headers.get(Authorization)
        if (auth_header):
            auth_tokenArr = auth_header.split(" ")
            if (not auth_tokenArr or auth_tokenArr[0]!= jwt or len(auth_tokenArr) != 2 ):
                result = common.falseReturn(‘‘,请传递正确的验证头信息)
            else:
                auth_token = auth_tokenArr[1]
                payload = self.decode_auth_token(auth_token)
                if not isinstance(payload, str):
                    userDao = UserDao()
                    user = userDao.search(payload[data][id])
                    if (user is None):
                        result = common.falseReturn(‘‘, 找不到该用户信息)
                    else:
                        result = common.trueReturn(‘‘, 请求成功)
                else:
                    result = common.falseReturn(‘‘, payload)
        else:
            result = common.falseReturn(‘‘,没有提供认证token)
        return result
View Code

代码说明:

authenticate: 根据用户名/密码,到DB中进行校验,如果是合法的用户名/密码,调用encode_auth_token生成token返回;username加入到token的payload中。
encode_auth_token:  生成token的函数,payload可以存储一些不敏感的信息,比如用户名等,但是不能存密码;还有指定签名算法和秘钥。
identify: 用户的请求需要携带token信息,这个函数对request进行校验,调用decode_auth_token完成的校验。
decode_auth_token: 调用jwt.decode进行token校验(要指定秘钥,秘钥和生成token的秘钥一样)

3.参数详解

exp是expires的简写,是用来指定token的生命周期

iss是issuer的简写,表明请求的实体,可以是发出请求的用户的信息

iss(签发者),exp(过期时间戳), sub(面向的用户), aud(接收方), iat(签发时间)

4.最简单的例子

加密

def _set_token(self, studentMids):
  doc = {
‘relate_info‘: {‘Phone‘: Phone,‘secret‘:self.Secret},
‘exp‘: datetime.datetime.utcnow() + datetime.timedelta(seconds=JWTConfig.EXP)
}
  encodeds = jwt.encode(
doc,
JWTConfig.SECRET_KEY,
algorithm=JWTConfig.ALGORITHM
)
  return encodeds

 

解密(主要还要看你自己写的加密规则来解密)

token = request.headers.get(Authorization)
           
            decryptData = token.split(".")[1] + "=" * (4 - len(token.split(".")[1]) % 4)
            secret = osjson.loads(base64.b64decode(decryptData))[relate_info][secret]
           separator = encrypt(CUSTOMSECRET, "")
      res = secret[::-1].split(str(base64.b64encode(separator.encode(utf-8)),"utf-8"))

5.奉送一个写的不错,特别详细的博客链接https://blog.csdn.net/cruise_h/article/details/50888225











以上是关于pyJWT的主要内容,如果未能解决你的问题,请参考以下文章

使用 PyJWT 在 Python 中解码 Firebase JWT

如何使用带有公共 PEM 证书的 python PyJWT 验证 JWT?

2015 年在 PyJWT 中发现的漏洞

如何确定 PyJWT 的版本?

pyJWT

PYJWT