• 264 第八篇:Django 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)

    View Code

    (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
    View Code

    (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, ]

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get(self, request):
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> HttpResponse(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">get</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> post(self, request):
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> HttpResponse(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">post</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
    
    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'))
    
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> md.hexdigest()+<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">|</span><span style="color: rgba(128, 0, 0, 1)">'</span>+<span style="color: rgba(0, 0, 0, 1)">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, ]

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get(self, request):
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> HttpResponse(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">get</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> post(self, request):
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> HttpResponse(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">post</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
    
    View Code

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

    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()</span></pre>
    
    View Code

    self.authenticators

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

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

  • 相关阅读:
    Django Web开发学习笔记(1)
    SessionFactory 执行原生态的SQL语句
    Java中使用FileputStream导致中文乱码问题的修改方案
    JavaScript中的namespace
    SpringMVC配置文件
    Python 贝叶斯分类
    Struct(二)
    Struct2 (一)
    SpingMVC ModelAndView, Model,Control以及参数传递
    window.onload
  • 原文地址:https://www.cnblogs.com/abdm-989/p/12168513.html
Copyright © 2020-2023  润新知