zoukankan      html  css  js  c++  java
  • python中的JWT

    为了解决Http无状态问题,产生了cookie和session技术。

     传统的session技术解决了无状态问题,但是不能防止客户端的篡改,而且对于服务端要保存session,在数据量较大,业务规模增加时,还要解决多台服务器之间的session共享问题,使用redis或者memcached等方案。

    产生可JWT技术可以解决用户篡改问题,服务器端产生的标识,使用算法加密,对标识签名。

    再次收到服务器端的标识,就要检查签名。

    这种方法在加密解密时,会消耗cpu计算资源,而且无法让浏览器自己检查过期数据,并且删除。

    下边我将尝试解释一下jwt防篡改的原理。

    JWT 全称(Json WEB Token)是一种采用Json方式安装传输信息的方式。

    python下的实现的pyjwt

    文档 : https://pyjwt.readthedocs.io/en/latest/

    安装 : pip install pyjwt

    先看以下代码:

    import jwt
    
    key = "secret"
    token = jwt.encode({"test": "100"},key,"HS256")
    print(token)
    header,payload,signature = token.split(b".")
    print(header)
    print(payload)
    print(signature)

    显示

    b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZXN0IjoiMTAwIn0.p2dBskystmxOlIXrBCowu6DPcWQbRrZMT3hJV7iMY-8'
    b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9'
    b'eyJ0ZXN0IjoiMTAwIn0'
    b'p2dBskystmxOlIXrBCowu6DPcWQbRrZMT3hJV7iMY-8'

    可以知道JWT由3段由点分割的部分组成。

    它使用的编码是base64编码,我们导入以下

    import jwt
    
    key = "secret"
    token = jwt.encode({"test": "100"},key,"HS256")
    print(token)
    header,payload,signature = token.split(b".")
    
    import base64
    
    def equal(b: bytes):
        """用来补齐被JWT去掉的等号"""
        rest = len(b) % 4
        return b + b'=' * rest
    
    print("header=",base64.urlsafe_b64decode(equal(header)))
    print("payout=", base64.urlsafe_b64decode(equal(payload)))
    print("signature", base64.urlsafe_b64decode(equal(signature)))

    显示:

    header= b'{"typ":"JWT","alg":"HS256"}'
    payout= b'{"test":"100"}'
    signature b'xa7gAxb2Lxacxb6lNx94x85xebx04*0xbbxa0xcfqdx1bFxb6LOxIWxb8x8ccxef'

    可以看到,JWT中传输的token内容由三部分组成

    • header 是由数据类型和加密算法组成
    • payload 是传输的数据部分,
    • signature 部分就时签名,是由前两部分和加密算法实现的,看以下代码

    下边是源码中的一部分,signing_input就是将前两部分转为JSON格式,再使用base64编码,连接起来,传入下边的方法中,alg_obj是方法,key是预处理key

    signing_input = b'.'.join(segments)
            try:
                alg_obj = self._algorithms[algorithm]
                key = alg_obj.prepare_key(key)
                signature = alg_obj.sign(signing_input, key)

    我们模仿一下,可得

    import jwt
    
    # Create your tests here.
    
    key = "secret"
    token = jwt.encode({"test": "100"},key,"HS256")
    header,payload,signature = token.split(b".")
    print(signature)
    
    import base64
    
    # def equal(b: bytes):
    #     """用来补齐被JWT去掉的等号"""
    #     rest = len(b) % 4
    #     return b + b'=' * rest
    
    # print("header=",base64.urlsafe_b64decode(equal(header)))
    # print("payout=", base64.urlsafe_b64decode(equal(payload)))
    # print("signature", base64.urlsafe_b64decode(equal(signature)))
    
    from jwt import algorithms
    alg = algorithms.get_default_algorithms()["HS256"]
    newkey = alg.prepare_key(key)
    signature_input = b".".join([header,payload])
    signature = alg.sign(signature_input,newkey)
    
    print(base64.urlsafe_b64encode(signature))

    显示,可以看到

    b'p2dBskystmxOlIXrBCowu6DPcWQbRrZMT3hJV7iMY-8'
    b'p2dBskystmxOlIXrBCowu6DPcWQbRrZMT3hJV7iMY-8='

    所以在密码相同时,传输相同的信息,得到的值是一样的。

    密码要足够强,且要足够安全。可以在测试下改变内容,看签名会不会改变。

    import jwt
    
    # Create your tests here.
    
    key = "secret"
    token = jwt.encode({"test": "100"},key,"HS256")
    header,payload,signature = token.split(b".")
    print(signature)
    
    import base64
    
    # def equal(b: bytes):
    #     """用来补齐被JWT去掉的等号"""
    #     rest = len(b) % 4
    #     return b + b'=' * rest
    
    # print("header=",base64.urlsafe_b64decode(equal(header)))
    # print("payout=", base64.urlsafe_b64decode(equal(payload)))
    # print("signature", base64.urlsafe_b64decode(equal(signature)))
    token = jwt.encode({"test": "1000"},key,"HS256") # 改变payload内容
    header,payload,signature = token.split(b".")
    
    from jwt import algorithms
    alg = algorithms.get_default_algorithms()["HS256"]
    newkey = alg.prepare_key(key)
    signature_input = b".".join([header,payload])
    signature = alg.sign(signature_input,newkey)
    
    print(base64.urlsafe_b64encode(signature))

    可以看到签名变了

    b'p2dBskystmxOlIXrBCowu6DPcWQbRrZMT3hJV7iMY-8'
    b'uCmPr1eOuLz8IDLQfN8t_DsyrB9PYfdvdueeHSBWN04='

    经过以上测试,可以知道,数据在使用JWT传输时,是明文传输的,注意不要传输敏感数据。

    JWT的防篡改还可以使用公钥,私钥,来防止用户被劫持的可能性。

    在用户登陆成功后可以使用JWT技术,登录后给用户JWT,用户发请求时加上jwt,服务器校验签名,通过就允许访问,在单点登陆时广泛应用。

  • 相关阅读:
    改造vant日期选择
    css3元素垂直居中
    npm综合
    (转)网页加水印方法
    Mac下IDEA自带MAVEN插件的全局环境配置
    隐藏注册控件窗口
    High performance optimization and acceleration for randomWalk, deepwalk, node2vec (Python)
    How to add conda env into jupyter notebook installed by pip
    The Power of WordNet and How to Use It in Python
    背单词app测评,2018年
  • 原文地址:https://www.cnblogs.com/rprp789/p/10017781.html
Copyright © 2011-2022 走看看