1. Token认证:
Token是一种用户身份的验证方式,通常叫做令牌验证。当用户第一次登录成功后,服务器会生成一个Token并将此Token返回给用户,以后用户只需要带上这个Token前来请求数据即可,无需再用用户名和密码。
2. Token验证过程
①首次登录时,客户端通过用户名与密码请求登录
②服务端收到请求并验证用户名与密码
③若验证通过,服务端会签发一个Token,该Token会保存在服务端的数据库中,并且也会返回给客户端
④客户端收到Token并存储起来,比如放在Cookie,SessionStorage,LocalStorage。
⑤客户端每次向服务端请求资源时都会带着Token
⑥服务端收到请求,然后验证客户端请求里面带着的Token,即将客户端的Token与本地数据库中的Token作对比,如果两个Token相同,说明用户曾登录成功过,则验证通过,服务端向客户端返回请求数据。
⑦若两个Token不同,则验证不通过,需要通过用户名和密码进行登录
3. 使用Token认证的原因:
当客户端多次向服务端请求数据时,服务端就需要多次从数据库中查询用户名和密码并进行比对,判断用户名和密码是否正确匹配,并作出相应提示。查询数据库是比较消耗资源的,这样无疑会增加服务器的运行压力。为了既能够验证用户登录情况又能够减轻服务器的压力,便引入了Token验证。Token一般是保存在内存中,这样的话就不用查询数据库,减少了频繁的查询数据库,使服务器更加健壮。
4. 自定义实现一个Token认证类
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
from app01.models import UserInfo, UserToken
def md5(user):
"""对用户token进行加密"""
import hashlib
import time
ctime = str(time.time())
m = hashlib.md5(bytes(str(user), encoding="utf-8"))
m.update(bytes(ctime, encoding="utf-8"))
return m.hexdigest()
class AuthView(APIView):
"""用于用户登录认证,认证成功创建Token,如果token已经存在就更新token"""
def post(self, request):
username = request._request.POST.get("username", "")
password = request._request.POST.get("password", "")
try:
user = UserInfo.objects.get(username=username, password=password)
except UserInfo.DoesNotExist:
res = {"status": 1000, "msg": "用户名或密码错误"}
else:
# 创建唯一的用户token
token = md5(user)
# 没有就创建,有了就更新
UserToken.objects.update_or_create(user=user, defaults={"token": token})
res = {"status": 1001, "msg": "认证成功", "token": token}
return JsonResponse(res)
class Authtication(BaseAuthentication):
"""用户是否登录成功认证类, 如果有token代表登录成功,如果没token代表登录失败"""
def authenticate(self, request):
token = request._request.GET.get("token")
user_token = UserToken.objects.filter(token=token).first()
if not user_token:
raise exceptions.AuthenticationFailed("用户认证失败")
# 传递的这个元组就会赋值给request对象的两个属性:request.user, request.auth
return (user_token.user, token)
def authenticate_header(self, request):
pass
class OrderViewAPIView(APIView):
authentication_classes = [Authtication]
def get(self, request):
# 此处的两个变量就是认证类里面认证成功后传递过来的元组
print(request.user, request.auth)
return JsonResponse({"status": 200, "msg": "首页"})