网站建设的各种组成,新闻今天,网站建设按年收费吗,产品设计排版模板基于Token的身份验证 在实现登录功能的时候,正常的B/S应用都会使用cookiesession的方式来做身份验证,后台直接向cookie中写数据,但是由于移动端的存在,移动端是没有cookie机制的,所以使用token可以实现移动端和客户端的token通信。 验证流程 整个基于Token的验证流程如下: 客户… 基于Token的身份验证 在实现登录功能的时候,正常的B/S应用都会使用cookiesession的方式来做身份验证,后台直接向cookie中写数据,但是由于移动端的存在,移动端是没有cookie机制的,所以使用token可以实现移动端和客户端的token通信。 验证流程 整个基于Token的验证流程如下: 客户端使用用户名跟密码请求登录服务器收到请求,去验证用户名和密码验证成功后,服务端会签发一个Token,再把这个Token发送到客户端客户端收到的Token以后可以把它存储起来,比如放在Cookie或LocalStorage里客户端每次向服务器发送其他请求的时候都要带着服务器签发的Token服务器收到请求,去验证客户端请求里面带着的Token,如果验证成功,就像客户端返回请求的数据 JWT 构造Token的方法挺多的,可以说只要是客户端和服务器端约定好了格式,是想怎么写就怎么写的,然而还有一些标准写法,例如JWT读作/jot/,表示:JSON Web Tokens. JWT标准的Token有三个部分: headerpayloadsignature 三个部分会用点分割开,并且都会使用Base64编码,所以真正的Token看起来像这样eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc Header header部分主要是两部分内容,一个是Token的类型,另一个是使用的算法,比如下面的类型就是JWT,使用的算法是HS256: {typ: JWT,alg: HS256
} 上面的内容要用 Base64 的形式编码一下所以就变成这样 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 Payload Payload 里面是 Token 的具体内容这些内容里面有一些是标准字段你也可以添加其它需要的内容。下面是标准字段 issIssuer发行者subSubject主题audAudience观众expExpiration time过期时间nbfNot beforeiatIssued at发行时间jtiJWT IDSignature JWT的最后一部分是Signature,这部分相当于前两段的摘要,用来防止其他人来篡改Token中的信息,在处理时可以首先将前两段生成的内容使用Base64生成一下再加盐然后利用MD5等摘要算法在生成一遍 服务端生成Token 在服务端生成Token的时候,需要解决两个问题 使用什么加密算法Token如何存储加密算法 这里的加密算法并不是MD5,SHA1这样的哈希算法,因为这种算法是无法解密的,只能用来生成摘要,在Django中内置了一个加密前面模块django.core.signing模块,可以用来加密和解密任何数据,使用签名模块的dumps和load函数来实现 示例: from django.core import signing
value signing.dumps({foo:bar})
src signing.loads(value)
print(value)
print(src) 结果: eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI
{‘foo’: ‘bar’} Token如何存储 用什么存储 在服务器中Token可以存储在内存中,因为本质是字符串,所以并不会占用很大的内存空间,如果是分布式的存储可以将所有的token信息分段存储在不同的服务器中,也可以存储在数据库中,在Django中提供了缓存类,可以用来存储Token,Django的缓存可以结合Redis来使用,可以借助django-redis来实现 安装 pip install django-redis 配置 为了使用django-redis,需要将django cache setting修改,修改settings.py,默认是没有Cache的配置信息的,在其中添加: CACHES {default: {BACKEND: django_redis.cache.RedisCache,LOCATION: redis://127.0.0.1:6379,OPTIONS: {CLIENT_CLASS: django_redis.client.DefaultClient,}}
} 当然,需要你首先安装了redis cache使用 cache使用的时候基本可以使用set和get方法来进行存/取数据 cache.set(my_key, hello, world!, 30)cache.get(my_key)
hello, world! 如何存 由于redis是使用k-v模式来进行存储数据的,我们可以使用用户名作为key,而token信息作为value,相较于直接使用token作为key的方式,好处是我们可以使用更少的空间实现一些功能,例如当用户修改了密码或点击注销之后,它的token可以直接失效,直接将该用户名所对应的数据删除就好了,或者用户在一次登录成功后,又一次请求了登录接口,我们可以很简单的更新该用户的token信息,而这样存储所依赖于我们的token可以进行解密,如果你是直接生成了一串无法解密的数据作为token,不能使用用户名作为token了 code import time
from django.core import signing
import hashlib
from django.core.cache import cacheHEADER {typ: JWP, alg: default}
KEY CHEN_FENG_YAO
SALT www.lanou3g.com
TIME_OUT 30 * 60 # 30mindef encrypt(obj):加密value signing.dumps(obj, keyKEY, saltSALT)value signing.b64_encode(value.encode()).decode()return valuedef decrypt(src):解密src signing.b64_decode(src.encode()).decode()raw signing.loads(src, keyKEY, saltSALT)print(type(raw))return rawdef create_token(username):生成token信息# 1. 加密头信息header encrypt(HEADER)# 2. 构造Payloadpayload {username: username, iat: time.time()}payload encrypt(payload)# 3. 生成签名md5 hashlib.md5()md5.update((%s.%s % (header, payload)).encode())signature md5.hexdigest()token %s.%s.%s % (header, payload, signature)# 存储到缓存中cache.set(username, token, TIME_OUT)return tokendef get_payload(token):payload str(token).split(.)[1]payload decrypt(payload)return payload# 通过token获取用户名
def get_username(token):payload get_payload(token)return payload[username]passdef check_token(token):username get_username(token)last_token cache.get(username)if last_token:return last_token tokenreturn False 转载于:https://www.cnblogs.com/Paul-watermelon/p/11286698.html