Django REST framework 認證、權限和頻率組件

認證與權限頻率組件

身份驗證是將傳入請求與一組標識憑據(例如請求來自的用戶或其簽名的令牌)相關聯的機制。然后 權限 和 限制 組件決定是否拒絕這個請求。

簡單來說就是:

  • 認證確定了你是誰
  • 權限確定你能不能訪問某個接口
  • 限制確定你訪問某個接口的頻率

一、認證組件

REST framework 提供了一些開箱即用的身份驗證方案,并且還允許你實現自定義方案。

自定義Token認證

定義一個用戶表和一個保存用戶Token的表:

class UserInfo(models.Model):username = models.CharField(max_length=16)password = models.CharField(max_length=32)type = models.SmallIntegerField(choices=((1, '普通用戶'), (2, 'VIP用戶')),default=1)class Token(models.Model):user = models.OneToOneField(to='UserInfo')token_code = models.CharField(max_length=128)

定義一個登錄視圖:

def get_random_token(username):"""根據用戶名和時間戳生成隨機token:param username::return:"""import hashlib, timetimestamp = str(time.time())m = hashlib.md5(bytes(username, encoding="utf8"))m.update(bytes(timestamp, encoding="utf8"))return m.hexdigest()class LoginView(APIView):"""校驗用戶名密碼是否正確從而生成token的視圖"""def post(self, request):res = {"code": 0}print(request.data)username = request.data.get("username")password = request.data.get("password")user = models.UserInfo.objects.filter(username=username, password=password).first()if user:# 如果用戶名密碼正確token = get_random_token(username)models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)res["token"] = tokenelse:res["code"] = 1res["error"] = "用戶名或密碼錯誤"return Response(res)

定義一個認證類

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailedclass MyAuth(BaseAuthentication):def authenticate(self, request):     # 必須實現authenticate方法,返回(認證之后的用戶,認證的obj)if request.method in ["POST", "PUT", "DELETE"]:request_token = request.data.get("token", None)if not request_token:raise AuthenticationFailed('缺少token')token_obj = models.Token.objects.filter(token_code=request_token).first()if not token_obj:raise AuthenticationFailed('無效的token')return token_obj.user.username, Noneelse:return None, None

視圖級別認證

class CommentViewSet(ModelViewSet):queryset = models.Comment.objects.all()serializer_class = app01_serializers.CommentSerializerauthentication_classes = [MyAuth, ]

全局級別認證

# 在settings.py中配置
REST_FRAMEWORK = {"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
}

二、權限組件

只有VIP用戶才能看的內容。

自定義一個權限類

# 自定義權限
class MyPermission(BasePermission):message = 'VIP用戶才能訪問'def has_permission(self, request, view):"""必須實現has_permission,有權限返回True,無權限返回False"""# 因為在進行權限判斷之前已經做了認證判斷,所以這里可以直接拿到request.userif request.user and request.user.type == 2:  # 如果是VIP用戶return Trueelse:return False

視圖級別配置

class CommentViewSet(ModelViewSet):queryset = models.Comment.objects.all()serializer_class = app01_serializers.CommentSerializerauthentication_classes = [MyAuth, ]permission_classes = [MyPermission, ]

全局級別設置

# 在settings.py中設置rest framework相關配置項
REST_FRAMEWORK = {"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
}

三、頻率限制組件

DRF內置了基本的限制類,首先我們自己動手寫一個限制類,熟悉下限制組件的執行過程。

自定義限制類

VISIT_RECORD = {}
# 自定義限制
class MyThrottle(object):def __init__(self):self.history = Nonedef allow_request(self, request, view): """必須實現allow_request,允許訪問返回True,否則返回False自定義頻率限制60秒內只能訪問三次"""# 獲取用戶IPip = request.META.get("REMOTE_ADDR")timestamp = time.time()if ip not in VISIT_RECORD:VISIT_RECORD[ip] = [timestamp, ]return Truehistory = VISIT_RECORD[ip]self.history = historyhistory.insert(0, timestamp)while history and history[-1] < timestamp - 60:history.pop()if len(history) > 3:return Falseelse:return Truedef wait(self):"""限制時間還剩多少"""timestamp = time.time()return 60 - (timestamp - self.history[-1])

視圖使用

class CommentViewSet(ModelViewSet):queryset = models.Comment.objects.all()serializer_class = app01_serializers.CommentSerializerthrottle_classes = [MyThrottle, ]

全局使用

# 在settings.py中設置rest framework相關配置項
REST_FRAMEWORK = {"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ],"DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
}

使用內置限制類

from rest_framework.throttling import SimpleRateThrottleclass VisitThrottle(SimpleRateThrottle):scope = "xxx"def get_cache_key(self, request, view):return self.get_ident(request)

全局配置

# 在settings.py中設置rest framework相關配置項
REST_FRAMEWORK = {"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],# "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]"DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ],"DEFAULT_THROTTLE_RATES": {"xxx": "5/m",}
}

認證類源碼

############################ authentication.py ####################################
from __future__ import unicode_literalsimport base64
import binasciifrom django.contrib.auth import authenticate, get_user_model
from django.middleware.csrf import CsrfViewMiddleware
from django.utils.six import text_type
from django.utils.translation import ugettext_lazy as _from rest_framework import HTTP_HEADER_ENCODING, exceptionsdef get_authorization_header(request):"""Return request's 'Authorization:' header, as a bytestring.Hide some test client ickyness where the header can be unicode."""auth = request.META.get('HTTP_AUTHORIZATION', b'')if isinstance(auth, text_type):# Work around django test client oddnessauth = auth.encode(HTTP_HEADER_ENCODING)return authclass CSRFCheck(CsrfViewMiddleware):def _reject(self, request, reason):# Return the failure reason instead of an HttpResponsereturn reasonclass BaseAuthentication(object):"""All authentication classes should extend BaseAuthentication."""def authenticate(self, request):"""Authenticate the request and return a two-tuple of (user, token)."""raise NotImplementedError(".authenticate() must be overridden.")def authenticate_header(self, request):"""Return a string to be used as the value of the `WWW-Authenticate`header in a `401 Unauthenticated` response, or `None` if theauthentication scheme should return `403 Permission Denied` responses."""passclass BasicAuthentication(BaseAuthentication):"""HTTP Basic authentication against username/password."""www_authenticate_realm = 'api'def authenticate(self, request):"""Returns a `User` if a correct username and password have been suppliedusing HTTP Basic authentication.  Otherwise returns `None`."""auth = get_authorization_header(request).split()if not auth or auth[0].lower() != b'basic':return Noneif len(auth) == 1:msg = _('Invalid basic header. No credentials provided.')raise exceptions.AuthenticationFailed(msg)elif len(auth) > 2:msg = _('Invalid basic header. Credentials string should not contain spaces.')raise exceptions.AuthenticationFailed(msg)try:auth_parts = base64.b64decode(auth[1]).decode(HTTP_HEADER_ENCODING).partition(':')except (TypeError, UnicodeDecodeError, binascii.Error):msg = _('Invalid basic header. Credentials not correctly base64 encoded.')raise exceptions.AuthenticationFailed(msg)userid, password = auth_parts[0], auth_parts[2]return self.authenticate_credentials(userid, password, request)def authenticate_credentials(self, userid, password, request=None):"""Authenticate the userid and password against username and passwordwith optional request for context."""credentials = {get_user_model().USERNAME_FIELD: userid,'password': password}user = authenticate(request=request, **credentials)if user is None:raise exceptions.AuthenticationFailed(_('Invalid username/password.'))if not user.is_active:raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))return (user, None)def authenticate_header(self, request):return 'Basic realm="%s"' % self.www_authenticate_realmclass SessionAuthentication(BaseAuthentication):"""Use Django's session framework for authentication."""def authenticate(self, request):"""Returns a `User` if the request session currently has a logged in user.Otherwise returns `None`."""# Get the session-based user from the underlying HttpRequest objectuser = getattr(request._request, 'user', None)# Unauthenticated, CSRF validation not requiredif not user or not user.is_active:return Noneself.enforce_csrf(request)# CSRF passed with authenticated userreturn (user, None)def enforce_csrf(self, request):"""Enforce CSRF validation for session based authentication."""check = CSRFCheck()# populates request.META['CSRF_COOKIE'], which is used in process_view()check.process_request(request)reason = check.process_view(request, None, (), {})if reason:# CSRF failed, bail with explicit error messageraise exceptions.PermissionDenied('CSRF Failed: %s' % reason)class TokenAuthentication(BaseAuthentication):"""Simple token based authentication.Clients should authenticate by passing the token key in the "Authorization"HTTP header, prepended with the string "Token ".  For example:Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a"""keyword = 'Token'model = Nonedef get_model(self):if self.model is not None:return self.modelfrom rest_framework.authtoken.models import Tokenreturn Token"""A custom token model may be used, but must have the following properties.* key -- The string identifying the token* user -- The user to which the token belongs"""def authenticate(self, request):auth = get_authorization_header(request).split()if not auth or auth[0].lower() != self.keyword.lower().encode():return Noneif len(auth) == 1:msg = _('Invalid token header. No credentials provided.')raise exceptions.AuthenticationFailed(msg)elif len(auth) > 2:msg = _('Invalid token header. Token string should not contain spaces.')raise exceptions.AuthenticationFailed(msg)try:token = auth[1].decode()except UnicodeError:msg = _('Invalid token header. Token string should not contain invalid characters.')raise exceptions.AuthenticationFailed(msg)return self.authenticate_credentials(token)def authenticate_credentials(self, key):model = self.get_model()try:token = model.objects.select_related('user').get(key=key)except model.DoesNotExist:raise exceptions.AuthenticationFailed(_('Invalid token.'))if not token.user.is_active:raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))return (token.user, token)def authenticate_header(self, request):return self.keywordclass RemoteUserAuthentication(BaseAuthentication):"""REMOTE_USER authentication.To use this, set up your web server to perform authentication, which willset the REMOTE_USER environment variable. You will need to have'django.contrib.auth.backends.RemoteUserBackend in yourAUTHENTICATION_BACKENDS setting"""# Name of request header to grab username from.  This will be the key as# used in the request.META dictionary, i.e. the normalization of headers to# all uppercase and the addition of "HTTP_" prefix apply.header = "REMOTE_USER"def authenticate(self, request):user = authenticate(remote_user=request.META.get(self.header))if user and user.is_active:return (user, None)

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454442.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454442.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454442.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

高速率AVS整數變換的匯編實現與優化

1 引言 AVS標準Ⅲ采用的8x8整數變換在獲得較H&#xff0e;264更高的壓縮率和主觀圖像質量的同時&#xff0c;增加了算法的實現復雜性和時間開銷。本文重點研究AVS編解碼器的整數變換模塊&#xff0c;針對不同的算法實現模式&#xff0c;在原有Visual C6&#xff0e;0整數變換模…

計算機與廣播電視論文,淺談廣播電視中計算機技術的作用論文.pdf

1、計算機技術在廣播電視的媒體內容中有重要應用在以往的廣播電視中&#xff0c; 媒體內容主要分為音頻和視頻兩種信號&#xff0c; 在傳輸的過程中使用的是模擬信號&#xff0c; 但模擬信號受到的外界干擾因素較為明顯&#xff0c; 因此廣播電視傳播的媒體內容受到影響&#x…

opencv安裝教程python3.7_Mac下安裝使用Python-OpenCV,解決opencv3安裝完成無法使用的問題 - pytorch中文網...

OpenCV是一個跨平臺計算機視覺庫&#xff0c;可以運行在Linux、Windows、Android和Mac OS操作系統上。提供了Python、Ruby、MATLAB等語言的接口&#xff0c;實現了圖像處理和計算機視覺方面的很多通用算法。 Mac安裝OpenCV 在我們的深度學習的過程中&#xff0c;對于圖像&#…

NodeJS在CentOs7下安裝

node下載地址:https://nodejs.org/en/download/ 1.安裝gcc $ yum install gcc-c 2.解壓最新版本 $ mkdir /usr/local/node$ tar zxvf node-v6.11.4.tar.gz $ cd node-v6.11.4$ ./configure --prefix/usr/local/node# 在當前目錄下編譯安裝Node$ make$ make install 3.驗證安裝 …

Python功能之反射

有如下文件: index.py 1<span style"font-family:宋體, SimSun;">#!/usr/bin/env python<br data-filtered"filtered"># -*- coding:utf-8 -*-<br data-filtered"filtered">__author__ ryan<br data-filtered"filter…

Django REST framework 分頁

分頁模式 rest framework中提供了三種分頁模式&#xff1a; from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination 全局配置 REST_FRAMEWORK {DEFAULT_PAGINATION_CLASS: rest_framework.pagination.LimitOffsetPaginat…

解析H.264視頻編解碼DSP實現與優化

引言 基于互聯網的數字視頻產業前景看好&#xff0c;而3G的規模部署&#xff0c;也會推動移動視頻通信成為現實。但數字化后的視頻圖像具有數據海量性&#xff0c;給圖像的存儲和傳輸造成較大的困難。數字視頻產業&#xff0c;是指數字內容中以數字視頻形態為主的文化創意和傳播…

ap計算機科學a買什么書,準備AP*計算機科學A考試-第1部分

你將學到什么Identify the use and proper use of Variables, Conditionals, Objects and primitives, control structures, booleans, lists and arrays, and Exceptions.Implement problem descriptions in well designed code.Identify and begin to design algorithms to s…

python 打包exe_python如何封裝為exe

1、首先進入python安裝路徑D:\Python27\Scripts下&#xff0c;查看pip或easy_install是否安裝。2、確保安裝了pip或者easy_install&#xff0c;在cmd命令行下輸入“easy_install”&#xff0c;沒有提示“xxx不是內部或外部命令……”&#xff0c;就說明easy install工具安裝成功…

CentOS7安裝Hadoop2.7完整步驟

總體思路&#xff0c;準備主從服務器&#xff0c;配置主服務器可以無密碼SSH登錄從服務器&#xff0c;解壓安裝JDK&#xff0c;解壓安裝Hadoop&#xff0c;配置hdfs、mapreduce等主從關系。 1、環境&#xff0c;3臺CentOS7&#xff0c;64位&#xff0c;Hadoop2.7需要64位Linux&…

Django REST framework 解析器和渲染器

解析器的作用 解析器的作用就是服務端接收客戶端傳過來的數據&#xff0c;把數據解析成自己可以處理的數據。本質就是對請求體中的數據進行解析。 在了解解析器之前&#xff0c;我們要先知道Accept以及ContentType請求頭。 Accept是告訴對方我能解析什么樣的數據&#xff0c…

MyBatis的學習之路(二)

上篇文章介紹了MyBatis的配置文件&#xff0c;現在來介紹實體映射文件Mapper.xml。 說道實體映射文件&#xff0c;就不得不說一下實體與表之間的映射關系&#xff1a;單表映射和多表映射。 a. 單表映射 1 public class Admin{ 2 private String id; 3 private String n…

計算機一級實驗素材題目,計算機一級EXCEL操作題整理素材(12頁)-原創力文檔...

素材摘錄&#xff0c;文檔可編輯分享PAGE 頁碼頁碼/NUMPAGES 總頁數總頁數單元格合并首先選中你要合并的單元格&#xff0c;然后找到EXCEL上的開始分區里的這種圖標或者是含有“合并”兩字的位置如圖1-1&#xff0c;如果題目要求的是要你合并單元格并讓內容居中&#xff0c;你就…

python爬取toefl_spark學習進度6-Python爬取數據的四個簡單實例

今天本來想把昨天安裝的intellij配置好&#xff0c;但是一直顯示沒有網絡&#xff0c;網上查了相關資料也沒有查出來解決辦法。然后暫停了intellij的配置&#xff0c;開始做了幾個Python爬取簡單數據的實例&#xff0c;先做了幾個最簡單的&#xff0c;以后再加大難度&#xff0…

Django REST framework 版本

API 版本控制允許我們在不同的客戶端之間更改行為&#xff08;同一個接口的不同版本會返回不同的數據&#xff09;。 DRF提供了許多不同的版本控制方案。 可能會有一些客戶端因為某些原因不再維護了&#xff0c;但是我們后端的接口還要不斷的更新迭代&#xff0c;這個時候通過…

AngularJS中的過濾器(filter)

AngularJS中的過濾器是用于對數據的格式化&#xff0c;或者篩選的函數&#xff0c;可以直接通過以下語法使用&#xff1a; {{expression|filter}} {{expression|filter1|filter2}} {{expression|filter1:param1,param2,...|filter2} 過濾器的種類有number&#xff0c;currency&…

計算機考試上傳照片教程,電腦照片傳到iPhone手機的詳細步驟【圖文】

蘋果自帶的iOS系統是不可以隨便和電腦進行數據交換的&#xff0c;必須使用iTunes軟件。許多用戶為此問題困擾&#xff0c;我們有什么可以把電腦照片傳到iPhone手機&#xff1f;下面我們就一起來看看把電腦照片傳到iphone設備的詳細步驟。具體方法如下&#xff1a;1&#xff0c;…

javaweb 導出文件名亂碼的問題解決方案

fileName new String(fileName.getBytes("ISO8859-1"), "UTF-8"); 或者 String finalFileName null; if(StringUtils.contains(userAgent, "MSIE")){//IE瀏覽器 finalFileName URLEncoder.encode(fileName,"UTF8"); }else if(Str…

AVS 分像素運動估計優化算法

—249—AVS 分像素運動估計優化算法楊涵悅 1&#xff0c;張兆楊1&#xff0c;滕國偉2(1. 上海大學通信學院&#xff0c;上海 200072&#xff1b;2. 上海廣電(集團)有限公司中央研究院&#xff0c;上海 200233)摘要&#xff1a;針對AVS 分像素運動估計的問題&#xff0c;提出一種…

計算機系統結構sw指令集,自考02325計算機系統結構復習資料六

自考生網為考生收集整理了“自考02325計算機系統結構復習資料六“以供考生們在考試前用復習資料鞏固所學到的知識&#xff0c;得到更好地復習效果。注&#xff1a;由于各省教材每年都有更新、變動&#xff0c;自考復習資料并不一定出于同一自考教材版本&#xff0c;但考生們仍可…