JWT学习小结

发布时间:2019-03-16 22:24:09编辑:auto阅读(1932)

    JWT全称JSON-Web-Tokens,是一套应对Http其无状态且明文传递请求的特性的规范,保证请求的安全性。我们一般用它来在服务端和客户端之间传递用户的身份信息,实现状态保持。

    1,相较于常见的session+cookie的实现方式,它有哪些优势呢?

      Session: 每次用户登录认证通过后,我们的应用都要在服务端(通常为redis服务器中)存储用户的登录信息,并在响应中设置cookies中设置session的key值进行返回。这在服务器实现负载均衡时,增加负载均衡服务器的性能负担。而面对CSRF攻击时, 因为是基于cookie+session的方式来进行用户识别的, cookie一旦被截获,用户就会很容易受到跨站请求伪造的攻击。

      JWT: 

    2,JWT的组成:

      JWT是一串加密后的字符串,共由三部分组成,分别为:头部,载荷和签名信息。

      头部(header)

    {
        "alg": "HS256",  # 使用的签名算法
        "typ": "JWT",  # 令牌的类型
                }

      载荷(payloader),用于存放有效信息。

    {
        "id": user.id,  # 接口中定义的需要返回的信息
        "mobile": user.mobile  # 同上
    }

      签名(signature),第三部分是将header和payload用base64进行转码后的字符串拼接的结果用header中指明的算法进行加密再用base64转码。

    def encode(payload, signer=None, encrypter=None):
        if signer and encrypter:
            raise SignAndEncryptError()
     
        headers = {'typ': 'JWT', 'alg': 'none'}
        if signer:
            #更新你所选用的算法,一般都是hs256
            headers.update(signer.headers)
        if encrypter:
            headers.update(encrypter.headers)
     
        #头部序列化
        headers_json = json.dumps(headers, separators=(',', ':'))
     
        #消息主体序列化
        payload_json = json.dumps(payload, separators=(',', ':'))
     
        #使用base64来编码
        header_b64 = b64encode(headers_json)
        payload_b64 = b64encode(payload_json)
     
        first_part = header_b64
        second_part = payload_b64
        third_part = ''
     
        if signer:
            #jwt 签名的生成方式. 他会把header playload的base64url编码加密后再次base64编码.
            third_part = b64encode(signer.sign(first_part + '.' +
                                                    second_part))
        if encrypter:
            pass  # TODO
        
        #返回可用的JWT
        return first_part + '.' + second_part + '.' + third_part
     
     
    def b64encode(data):
        return base64.urlsafe_b64encode(data).rstrip('=')
     
     
    #使用hmac来加密
     
    class HmacSha(JwsBase):
        def sign(self, signing_input, key=None):
            if not key:
                key = self.key
            if not key:
                raise KeyRequiredException()
            return hmac.new(key, signing_input, self.digestmod).digest()

    3、JWT的防篡改

      加密后的Token在下次请求时, 服务端通过加密生成的私钥,重新与前2部分组合再次加密,与第三部分进行对比,如果校验成功,则数据没有被修改。

    4、JWT防止CSRF攻击

      客户端使用 auth授权头认证,token存储在 cookie中,需要防止xss攻击。可以防止 csrf攻击,因为 csrf只能在请求中携带 cookie,而这里必须从 cookie中拿出相应的值并放到 authorization 头中。实际上cookie不能跨站(同源政策)被取出,因此可以避免 csrf 攻击。(适用于 ajax请求或者 api请求,可以方便的设置 auth头)。
      也可以将token存储在 localstorage里面,需要防止xss攻击。实现方式可以在一个统一的地方复写请求头,让每次请求都在header中带上这个token, 当token失效的时候,后端肯定会返回401,这个时候在你可以在前端代码中操作返回登陆页面,清除localstorage中的token。(适用于 ajax请求或者 api请求,可以方便的存入 localstorage)。

关键字

上一篇: selenium+webDriver+h

下一篇: Python-JSON和pickle