jwt應用 rbac django快取
阿新 • • 發佈:2020-07-20
1 jwt
1.1 控制使用者登入後才能訪問,和不登入就能訪問
# 1 控制使用者登入後才能訪問,和不登入就能訪問 from rest_framework.permissions import IsAuthenticated class OrderAPIView(APIView):# 登入才能 authentication_classes = [JSONWebTokenAuthentication,] # 許可權控制 permission_classes = [IsAuthenticated,] def get(self,request,*args,**kwargs): return Response('這是訂單資訊') class UserInfoAPIView(APIView):# 不登入就可以 authentication_classes = [JSONWebTokenAuthentication,] # 許可權控制 # permission_classes = [IsAuthenticated,] def get(self,request,*args,**kwargs): return Response('UserInfoAPIView')
1.2 控制登入介面返回的資料格式
# 2 控制登入介面返回的資料格式
-第一種方案,自己寫登入介面
-第二種寫法,用內建,控制登入介面返回的資料格式
-jwt的配置資訊中有這個屬性
'JWT_RESPONSE_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_response_payload_handler',
-重寫jwt_response_payload_handler,配置成咱們自己的
1.3 自定義基於jwt的許可權類
# 3 自定義基於jwt的許可權類 from rest_framework.authentication import BaseAuthentication # 基於它 from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication # 基於它 from rest_framework.exceptions import AuthenticationFailed # from rest_framework_jwt.authentication import jwt_decode_handler from rest_framework_jwt.utils import jwt_decode_handler # 跟上面是一個 import jwt from api import models # class MyJwtAuthentication(BaseAuthentication): # def authenticate(self, request): # jwt_value=request.META.get('HTTP_AUTHORIZATION') # if jwt_value: # try: # #jwt提供了通過三段token,取出payload的方法,並且有校驗功能 # payload=jwt_decode_handler(jwt_value) # except jwt.ExpiredSignature: # raise AuthenticationFailed('簽名過期') # except jwt.InvalidTokenError: # raise AuthenticationFailed('使用者非法') # except Exception as e: # # 所有異常都會走到這 # raise AuthenticationFailed(str(e)) # # 因為payload就是使用者資訊的字典 # print(payload) # # return payload, jwt_value # # 需要得到user物件, # # 第一種,去資料庫查 # # user=models.User.objects.get(pk=payload.get('user_id')) # # 第二種不查庫 # user=models.User(id=payload.get('user_id'),username=payload.get('username')) # return user,jwt_value # # 沒有值,直接拋異常 # raise AuthenticationFailed('您沒有攜帶認證資訊') class MyJwtAuthentication(BaseJSONWebTokenAuthentication): def authenticate(self, request): jwt_value=request.META.get('HTTP_AUTHORIZATION') if jwt_value: try: #jwt提供了通過三段token,取出payload的方法,並且有校驗功能 payload=jwt_decode_handler(jwt_value) except jwt.ExpiredSignature: raise AuthenticationFailed('簽名過期') except jwt.InvalidTokenError: raise AuthenticationFailed('使用者非法') except Exception as e: # 所有異常都會走到這 raise AuthenticationFailed(str(e)) user=self.authenticate_credentials(payload) return user,jwt_value # 沒有值,直接拋異常 raise AuthenticationFailed('您沒有攜帶認證資訊')
1.4 手動簽發token(多方式登入)
# 使用使用者名稱,手機號,郵箱,都可以登入# # 前端需要傳的資料格式 { "username":"lqz/1332323223/[email protected]", "password":"lqz12345" } # 檢視 from rest_framework.views import APIView from rest_framework.viewsets import ViewSetMixin, ViewSet from app02 import ser class Login2View(ViewSet): # 跟上面完全一樣 def login(self, request, *args, **kwargs): # 1 需要 有個序列化的類 login_ser = ser.LoginModelSerializer(data=request.data,context={'request':request}) # 2 生成序列化類物件 # 3 呼叫序列號物件的is_validad login_ser.is_valid(raise_exception=True) token=login_ser.context.get('token') # 4 return return Response({'status':100,'msg':'登入成功','token':token,'username':login_ser.context.get('username')}) # 序列化類 from rest_framework import serializers from api import models import re from rest_framework.exceptions import ValidationError from rest_framework_jwt.utils import jwt_encode_handler,jwt_payload_handler class LoginModelSerializer(serializers.ModelSerializer): username=serializers.CharField() # 重新覆蓋username欄位,資料中它是unique,post,認為你儲存資料,自己有校驗沒過 class Meta: model=models.User fields=['username','password'] def validate(self, attrs): print(self.context) # 在這寫邏輯 username=attrs.get('username') # 使用者名稱有三種方式 password=attrs.get('password') # 通過判斷,username資料不同,查詢欄位不一樣 # 正則匹配,如果是手機號 if re.match('^1[3-9][0-9]{9}$',username): user=models.User.objects.filter(mobile=username).first() elif re.match('^.+@.+$',username):# 郵箱 user=models.User.objects.filter(email=username).first() else: user=models.User.objects.filter(username=username).first() if user: # 存在使用者 # 校驗密碼,因為是密文,要用check_password if user.check_password(password): # 簽發token payload = jwt_payload_handler(user) # 把user傳入,得到payload token = jwt_encode_handler(payload) # 把payload傳入,得到token self.context['token']=token self.context['username']=user.username return attrs else: raise ValidationError('密碼錯誤') else: raise ValidationError('使用者不存在')
1.5 jwt的配置引數
# jwt的配置
import datetime
JWT_AUTH={
'JWT_RESPONSE_PAYLOAD_HANDLER':'app02.utils.my_jwt_response_payload_handler',
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), # 過期時間,手動配置
}
2 基於角色的許可權控制(django內建auth體系)
# RBAC :是基於角色的訪問控制(Role-Based Access Control ),公司內部系統
# django的auth就是內建了一套基於RBAC的許可權系統
# django中
# 後臺的許可權控制(公司內部系統,crm,erp,協同平臺)
user表
permssion表
group表
user_groups表是user和group的中間表
group_permissions表是group和permssion中間表
user_user_permissions表是user和permission中間表
# 前臺(主站),需要用三大認證
# 演示:
3 django快取
# 前端混合開發快取的使用
-快取的位置,通過配置檔案來操作(以檔案為例)
-快取的粒度:
-全站快取
中介軟體
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
。。。。
'django.middleware.cache.FetchFromCacheMiddleware',
]
CACHE_MIDDLEWARE_SECONDS=10 # 全站快取時間
-單頁面快取
在檢視函式上加裝飾器
from django.views.decorators.cache import cache_page
@cache_page(5) # 快取5s鍾
def test_cache(request):
import time
ctime=time.time()
return render(request,'index.html',context={'ctime':ctime})
-頁面區域性快取
{% load cache %}
{% cache 5 'name' %} # 5表示5s鍾,name是唯一key值
{{ ctime }}
{% endcache %}
# 前後端分離快取的使用
- 如何使用
from django.core.cache import cache
cache.set('key',value可以是任意資料型別)
cache.get('key')
-應用場景:
-第一次查詢所有圖書,你通過多表聯查序列化之後的資料,直接快取起來
-後續,直接先去快取查,如果有直接返回,沒有,再去連表查,返回之前再快取
補充
1 補充base64使用
# base64編碼和解碼
#md5固定長度,不可反解
#base63 變長,可反解
#編碼(字串,json格式字串)
import base64
import json
dic={'name':'lqz','age':18,'sex':'男'}
dic_str=json.dumps(dic)
ret=base64.b64encode(dic_str.encode('utf-8'))
print(ret)
# 解碼
# ret是帶解碼的串
ret2=base64.b64decode(ret)
print(ret2)