只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查询,没有登录就不能查看 ,这时候就要用到认证组件
(1)models层
class UserInfo(models.Model):
name = models.CharField(max_length=32)
user_choice = ((0, '普通用户'), (1, '会员'), (2, '超级用户'))
# 指定choice,可以快速 的通过数字,取出文字
user_type = models.IntegerField(choices=user_choice, default=0)
pwd = models.CharField(max_length=32)
class UserToken(models.Model):
# token随机字符串
token = models.CharField(max_length=64)
user = models.OneToOneField(to=UserInfo)
View Code
(2)新建认证类(验证通过 return 两个参数)
# 用drf的认证,写一个类
class LoginAuth():
# 函数名一定叫authenticate,接收 必须两个参数,第二个 参数是request对象
def authenticate(self, request):
# 从request对象中取出token(也可以从其他地方取)
token = request.query_params.get('token')
# 去数据库过滤,查询
ret = models.UserToken.objects.filter(token=token).first()
if ret:
# 认证多个 ,用None ; authentication_classes = [LoginAuth, ]
# return None
return ret.user, ret
# 如果查询不到抛异常
raise exceptions.APIException('您认证失败')
View Code
(3)view层
class Login(APIView):
# 空,局部禁用
authentication_classes = []
def post(self, request, *args, **kwargs):
response = {'status': 100, 'msg': '登录成功'}
name = request.data.get('name')
pwd = request.data.get('pwd')
try:
user = models.UserInfo.objects.get(name=name, pwd=pwd)
# 校验通过,登录成功,生成一个随机字符串,token
token = get_token(name)
# 保存到数据库,update_or_create,有跟新,没有创建
# 修改或新增的东西放在defaults中
models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
response['token'] = token
except ObjectDoesNotExist as e:
response['status'] = 101
response['msg'] = '用户名或密码错误'
except Exception as e:
response['status'] = 102
# response['msg']='未知错误'
response['msg'] = str(e)
return JsonResponse(response, safe=False)
View Code
附:不存数据库的token验证
def get_token(id,salt='123'):
import hashlib
md=hashlib.md5()
md.update(bytes(str(id),encoding='utf-8'))
md.update(bytes(salt,encoding='utf-8'))
return md.hexdigest()+'|'+str(id)
def check_token(token,salt='123'):
ll=token.split('|')
import hashlib
md=hashlib.md5()
md.update(bytes(ll[-1],encoding='utf-8'))
md.update(bytes(salt,encoding='utf-8'))
if ll[0]==md.hexdigest():
return True
else:
return False
class TokenAuth():
def authenticate(self, request):
token = request.GET.get('token')
success=check_token(token)
if success:
return
else:
raise AuthenticationFailed('认证失败')
def authenticate_header(self,request):
pass
class Login(APIView):
def post(self,reuquest):
back_msg={'status':1001,'msg':None}
try:
name=reuquest.data.get('name')
pwd=reuquest.data.get('pwd')
user=models.User.objects.filter(username=name,password=pwd).first()
if user:
token=get_token(user.pk)
# models.UserToken.objects.update_or_create(user=user,defaults={'token':token})
back_msg['status']='1000'
back_msg['msg']='登录成功'
back_msg['token']=token
else:
back_msg['msg'] = '用户名或密码错误'
except Exception as e:
back_msg['msg']=str(e)
return Response(back_msg)
from rest_framework.authentication import BaseAuthentication
class TokenAuth():
def authenticate(self, request):
token = request.GET.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if token_obj:
return
else:
raise AuthenticationFailed('认证失败')
def authenticate_header(self,request):
pass
class Course(APIView):
authentication_classes = [TokenAuth, ]
def get(self, request):
return HttpResponse('get')
def post(self, request):
return HttpResponse('post')
View Code
REST_FRAMEWORK={
'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',],
'DEFAULT_PERMISSION_CLASSES':['app01.MyAuth.UserPermission',]
}
总结:局部使用,只需要在视图类加入:
authentication_classes = [TokenAuth, ]