当用户提起http请求的时候,需要做身份认证。不可能每次提起http请求都发送用户名和密码,这不现实也不安全。这时,token就派上了用场。
用户在登录时提交用户名和密码进行认证。认证通过,服务器就给用户下发一个token。在以后的每次请求中,用户提交这个token给服务器验证自己的身份,而不是用户名和密码。
JSON Web Token(JWT)是一个轻巧的规范。在浏览器访问中,结合Cookie使用。下面是自定义的,简化的token实现。
产生token的过程:
1.生成json信息,包含用户名和token的过期时间
2.把json进行base64编码
3.根据用户名查找对应的key,对json的base64编码计算hash值
4.把hash值进行base64编码
5.token由json信息和hash值组装而成
验证token的过程:
1.分离json信息和hash值
2.json信息中分离出用户名,用于查找对应的key
3.用key重新计算hash值,与token中的hash值进行比较
4.判断是否过期,当前时间与token过期时间比较
5.如果两个判断都通过,则token验证通过
用户名对应的key存储在服务端,不会在网络上传输。攻击者无法获取key,也就无法伪造token。用户提交token以验证自己的身份。
以下是python实现:
import hmac
import time
import base64
import json
TOKEN_SPLIT = '.'
KEY_ID = 'id'
KEY_EXP = 'exp'
INDEX_INFO = 0
INDEX_HASH = 1
def genToken(keyList, name):
info = {KEY_ID:name, KEY_EXP:time.time() + 36000}
infoJson = json.dumps(info, ensure_ascii=False, encoding='utf-8')
infoCode = base64.urlsafe_b64encode(infoJson)
encrypt = hmac.new(keyList[name])
encrypt.update(infoCode)
hashHex = encrypt.hexdigest()
hashCode = base64.urlsafe_b64encode(hashHex)
token = infoCode + TOKEN_SPLIT + hashCode
return token
def verifyToken(keyList, token):
token = token.split('.')
infoCode = token[INDEX_INFO]
infoJson = base64.urlsafe_b64decode(infoCode).decode('utf-8')
info = json.loads(infoJson, encoding='utf-8')
name = info[KEY_ID]
expTime = info[KEY_EXP]
encrypt = hmac.new(keyList[name])
encrypt.update(infoCode)
hashHex = encrypt.hexdigest()
hashCode = base64.urlsafe_b64encode(hashHex)
return token[INDEX_HASH] == hashCode and time.time() < expTime
if __name__ == "__main__":
keyList = {'id123':'asdb', 'id456':'asdfsfs'}
token = genToken(keyList, 'id456')
print(token)
verify = verifyToken(keyList, token)
print(verify)