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里配置的验证类,最后用默认的验证类

 

posted @ 2020-01-08 20:01  ABDM  阅读(148)  评论(0编辑  收藏  举报