Json Web Token(JWT)简介

JSON Web Token的结构

JSON Web Token包含用点(.)分隔的三部分:

  • Header(头)
  • Payload
  • Signature(签名)

因此,一个JWT的形式是:
xxxxx.yyyyy.zzzzz


Header通常包含两部分:

  • token的类型(就是JWT)
  • 哈希算法(比如:HMAC SHA256或RSA)

下面是一个例子:

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


使用Base64Url对Header进行编码,形成JWT的第一部分。


Payload

JWT的第二部分是payload,它包含声明。声明是关于实体(实体通常是用户)和可选的元数据的一系列语句。有三种类型的声明:预留的、公有的、私有的。

  • 预留的声明:
    预留的声明是一组预定义的声明。不强制,但是推荐使用它们。预留的声明包括:iss(issuer)-请求的发起人,exp(expiration time)-以秒为单位的过期时间,sub (subject)-主题,aud (audience)-参与者,等等。注意:预留的声明的名称的长度都是3。
  • 公有的声明:
    在使用公有的声明的时候应避免名称冲突。
  • 私有的声明:
    私有的声明是自定义的声明,用于在系统的各部分之间共享信息。

下面是一个例子:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}


使用Base64Url对Payload进行编码,形成JWT的第二部分。


Signature

签名部分是使用编码后的header编码后的payload密钥以及header中指定的算法生成的。
比如,算法是HMAC SHA256,那么签名的计算方式是:

HMACSHA256(  
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)


签名用于核实JWT的发送者,并确保消息没有被篡改。


合并起来

JWT包含三个用点分隔的Base64字符串。
下面是一个JWT的例子:
jwt


使用示例(Python)

思路是:将公钥给客户端,客户端使用公钥把数据加密发送给服务器端,服务器端根据信息的来源,使用对应的私钥进行解密。
需要安装的模块:
sudo easy_install pycrypto
sudo easy_install python_jwt

代码如下:

#coding: utf8

import datetime

import jwt  
import Crypto.PublicKey.RSA as RSA

def gen_rsa_keys(bits):  
    #随机地生成一个RSA key
    key = RSA.generate(bits)
    #返回编码后的私钥(str)
    priv_pem = key.exportKey()
    #返回编码后的公钥(str)
    pub_pem = key.publickey().exportKey()
    return priv_pem, pub_pem

def gen_rsa(bits=2048):  
    priv_pem, pub_pem = gen_rsa_keys(bits)
    #导入RSA密钥(公钥或私钥),编码成标准形式
    return RSA.importKey(priv_pem), RSA.importKey(pub_pem)

priv_key, pub_key = gen_rsa(1024)  
payload = {'foo': 'bar', 'wup': 90}

def client_side():  
    return jwt.generate_jwt(payload, priv_key, 'RS256',
                datetime.timedelta(minutes=5))

def server_side(token):  
    return jwt.verify_jwt(token, pub_key, ['RS256'])

if __name__ == "__main__":  
    token = client_side()
    print token
    header, claims = server_side(token)
    print header
    print claims


输出:

eyJhbGciOiAiUlMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ3dXAiOiA5MCwgImp0aSI6ICJ5c090a2hEamhVaFZJTWtBMTQzdG13PT0iLCAiZXhwIjogMTQ1NDQ5NjU5NywgImlhdCI6IDE0NTQ0OTYyOTcsICJmb28iOiAiYmFyIiwgIm5iZiI6IDE0NTQ0OTYyOTd9.m_iHtfNz1wXzcBDMBMexPcgqKVQeJv6ngL3hagMHPnNPhq7kaBbaG0D0pYHfF6AZmItc3842dRjkJs4YwOV8jepdfbKjDBcUkcIXiQTw2ccAY69L2NDjEV-IHKAPGMulFwBykKNr0Ibdu185vWW8Wy6Hy15mskeTuwJ_fIrNZrM  
{u'alg': u'RS256', u'typ': u'JWT'}
{u'wup': 90, u'jti': u'ysOtkhDjhUhVIMkA143tmw==', u'exp': 1454496597, u'iat': 1454496297, u'foo': u'bar', u'nbf': 1454496297}

JTI和replay attack

重放攻击(Replay Attacks)又称重播攻击、回放攻击或新鲜性攻击(Freshness Attacks),是指攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程,破坏认证的正确性。
jti是被放到JWT中的唯一的ID,可以防止重放攻击。


参考文档

感谢浏览tim chow的作品!

如果您喜欢,可以分享到: 更多

如果您有任何疑问或想要与tim chow进行交流

可点此给tim chow发信

如有问题,也可在下面留言: