对当前用户,使用base64加密token,再解密token,但是不如JWT加密安全
import time
import base64
import hmac
def generate_token(key, expire=3600):
r'''
@Args:
key: str (用户给定的key,需要用户保存以便之后验证token,每次产生token时的key 都可以是同一个key)
expire: int(最大有效时间,单位为s)
@Return:
state: str
'''
ts_str = str(time.time() + expire)
ts_byte = ts_str.encode("utf-8")
sha1_tshexstr = hmac.new(key.encode("utf-8"),ts_byte,'sha1').hexdigest()
token = ts_str+':'+sha1_tshexstr
b64_token = base64.urlsafe_b64encode(token.encode("utf-8"))
return b64_token.decode("utf-8")
# 解密,验证token
def certify_token(key, token):
token_str = base64.urlsafe_b64decode(token).decode('utf-8')
# print(token_str)
token_list = token_str.split(':')
if len(token_list) != 2:
return False
ts_str = token_list[0]
if float(ts_str) < time.time():
# token expired
return False
known_sha1_tsstr = token_list[1]
sha1 = hmac.new(key.encode("utf-8"),ts_str.encode('utf-8'),'sha1')
calc_sha1_tsstr = sha1.hexdigest()
print(token_list)
print(calc_sha1_tsstr)
print(known_sha1_tsstr)
if calc_sha1_tsstr != known_sha1_tsstr:
# token certification failed
return False
# token certification success
return True
# 一小时后过期
#将key设置为username
token = generate_token('dujufei', 3600)
#使用当前用户名去认证token,看当前登录用户是否合法。合法,返回True
status=certify_token('dujufei', token)
print(token)
#MTU1NjEzMDAxMy4wNDMwNjg2OjFkYjg2NzE4YjIxZGIwNjAwMmVjYTQyNjRhZmRiY2JmYTNjMzZiNzU=
print(status)
#True
使用token进行当前用户状态保存,传给前端token
# token_test.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.shortcuts import render,redirect,HttpResponse
from rbac.models import UserInfo,UserToken
import time
import hashlib
def get_token(user):
# 获取一个字符串类型的时间戳时间
str_ctime = str(time.time())
# 生成一个加盐的hashlib对象
md5 = hashlib.md5(bytes(user,encoding='utf-8'))
# 给随机生成的字符串加密
md5.update(bytes(str_ctime,encoding='utf-8'))
# 返回加密后的字节型数据
return md5.hexdigest()
class LoginView(APIView):
'''登录视图是校验逻辑接口,不需要用视图类组件'''
def post(self,request):
resp = {'code': 100}
try:
# 获取前端通过POST请求发送过来的数据
user = request.data.get('username')
pwd = request.data.get('password')
# 查找数据库中是否有此用户
user_obj = UserInfo.objects.filter(name=user,password=pwd).first()
if user_obj:
# 如果数据库中有此用户,就做以下内容:
# 1.将此用户名返回给前端
resp['user'] = user
# 2.将随机生成一个字符串作为Token值返回给前端
token = get_token(user)
resp['user_token'] = token
# 将随机生成的token保存在数据库中
UserToken.objects.update_or_create(user=user_obj,defaults={'usertoken':token})
else:
resp['code'] = 1001
resp['error'] = '用户名或者密码错误'
except Exception as e:
resp['code'] = 1002
resp['error'] = str(e)
return Response(resp)
# models.py
class UserInfo(models.Model):
"""
用户表
"""
name = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
email = models.CharField(verbose_name='邮箱', max_length=32)
roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)
def __str__(self):
return self.name
class UserToken(models.Model):
'''
token认证表
'''
usertoken=models.CharField(verbose_name='令牌',max_length=128)
user=models.OneToOneField(to='UserInfo',on_delete=models.CASCADE)
def __str__(self):
return self.user.name
效果:
发送:对当前url http://192.168.174.1:8022/login_test/ 点击post请求发送一下数据
{
"username": "杜志浩",
"password": 123
}
返回:前端得到以下信息:
{
"code": 100,
"user": "杜志浩",
"user_token": "443497bf67071775d8db8180af6eb848"
}