认证简介

rest-framework之认证组件

一 认证简介

只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查看,没有登录,就不能查看,这时候需要用到认证组件

二 局部使用

(1)models层:

认证简介

class User(models.Model):
  username=models.CharField(max_length=32)
  password=models.CharField(max_length=32)
  user_type=models.IntegerField(choices=((1,'超级用户'),(2,'普通用户'),(3,'二笔用户')))

class UserToken(models.Model):
  user=models.OneToOneField(to='User')
  token=models.CharField(max_length=64)

认证简介

(2)新建认证类(验证通过return两个参数)

认证简介

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

认证简介

(3)view层

认证简介

def get_random(name):
  import hashlib
  import time
  md=hashlib.md5()
  md.update(bytes(str(time.time()),encoding='utf-8'))
  md.update(bytes(name,encoding='utf-8'))
  return md.hexdigest()
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_random(name)
              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)



class Course(APIView):
  authentication_classes = [TokenAuth, ]

  def get(self, request):
      return HttpResponse('get')

  def post(self, request):
      return HttpResponse('post')

认证简介

附:不存数据库的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')

认证简介

总结:局部使用,只需要在视图类里加入:

authentication_classes = [TokenAuth, ]

三 全局使用

REST_FRAMEWORK={
  "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",]
}

四 源码分析

认证简介

#Request对象的user方法
@property
def user(self):
the authentication classes provided to the request.
      if not hasattr(self, '_user'):
          with wrap_attributeerrors():
              self._authenticate()
      return self._user

def _authenticate(self):
      for authenticator in self.authenticators:
          try:
              user_auth_tuple = authenticator.authenticate(self)
          except exceptions.APIException:
              self._not_authenticated()
              raise
          #认证成功,可以返回一个元组,但必须是最后一个验证类才能返回
          if user_auth_tuple is not None:
              self._authenticator = authenticator
              self.user, self.auth = user_auth_tuple
              return

      self._not_authenticated()

认证简介

self.authenticators

    def get_authenticators(self):
      return [auth() for auth in self.authentication_classes]

认证类使用顺序:先用视图类中的验证类,再用settings里配置的验证类,最后用默认的验证类

上一篇:接口测试中,如何优雅的解决用例之间参数调用?


下一篇:Spring Security 应用实践