rest-framework之認證元件
阿新 • • 發佈:2018-11-23
認證元件
認證簡介
作用:校驗是否登入
- 首先定義一個類,整合BaseAuthentication,寫一個方法:authenticate,在方法內部,實證過程,認證通過,返回None或者兩個物件(user,auth),這兩個物件,在檢視類的request中可以取出來
from rest_framework.authentication import BaseAuthentication class myAuthen(BaseAuthentication): def authenticate(self, request): token = request.query_params.get('token') ret = models.UserToken.objects.filter(token=token).first() if ret: # return ret.user, ret # 要寫多個認證類,這個地返回None # 最後一個認證類,返回這倆值 return ret.user, ret else: raise AuthenticationFailed('您沒有登陸')
- 區域性使用:只需要在檢視類中加入(可以寫多個)
authentication_classes = [myAuthen, ]
- 全域性使用 setting中設定
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",]
}
認證順序
認證類使用順序:先用檢視類中的驗證類,再用settings裡配置的驗證類,最後用預設的驗證類
區域性使用例子
- 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)
- 新建認證類(驗證通過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層
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')
全域性使用 在setting中新增
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]