人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

django restframework使用redis實現(xiàn)token認證

發(fā)布日期:2022-01-02 01:27 | 文章來源:源碼之家

一、

restframework有自己很方便的一套認證、權(quán)限體系:官方文檔(tokenauthentication)

官方文檔的token 是基于數(shù)據(jù)庫中的authtoken_token表來做的

有時候在后續(xù)接口中需要使用的用戶信息過多時,頻繁、高并發(fā)下的查詢數(shù)據(jù)庫會帶來比較大的性能消耗。這個時候我們就需要通過redis來做用戶認證,并存儲一些用戶信息在其中。下面就為你講解如何基于redis來使用DRF做用戶認證。

二、詳解

1. 前期準備

1.1 安裝redis并啟動

自行安裝!這個都裝不好后面的教程也不用看了!看了也理解不了!

1.2 安裝django-redis庫

pip install django-redis -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 配置redis

2.1 配置redis連接

settings.py輸入下面的代碼 (我的redis沒有設(shè)置密碼,所以配置代碼中無密碼相關(guān)配置)

# redis緩存配置
CACHES = {
 "default": {
  "BACKEND": "django_redis.cache.RedisCache",
  "LOCATION": "redis://127.0.0.1:6379/",
  "OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.zlib.ZlibCompressor",
"IGNORE_EXCEPTIONS": True,
  }
 }
}

2.2 初始化redis連接

在項目初始化文件中(__init__.py)加入下面代碼進行redis的初始化

加入下列代碼

from django_redis import get_redis_connection
redis_connect = get_redis_connection()

3. 將token寫入redis

在之前的登錄接口是將token寫入數(shù)據(jù)庫的,現(xiàn)在需要重寫它讓其寫入redis

3.1 原來的登錄代碼

@api_view(['POST'])
def login(request):
 """
 登錄接口
 """
 user = authenticate(username=request.data['username'], password=request.data['password'])
 if user:
  Token.objects.filter(user_id=user.id).delete()
  token = Token.objects.create(user=user)
  _dict = {'id': user.id, 'username': user.username, 'first_name': user.first_name,
  'last_name': user.last_name, 'email': user.email}  
  redis_connect.set(token.key, json.dumps(_dict), 259200)  # 存redis 259200秒=72個小時
  return Response(data={'status_code': 200, 'msg': '登錄成功!', 'token': token.key})
 return Response(data={'status_code': 403, 'msg': '密碼錯誤!'})

3.2 重寫后的登錄代碼

@api_view(['POST'])
def login(request):
 """
 登錄接口
 """
 user = authenticate(username=request.data['username'], password=request.data['password'])
 if user:
  token = binascii.hexlify(os.urandom(20)).decode()  # 生成token 的方式
  _dict = {'id': user.id, 'username': user.username, 'first_name': user.first_name,
  'last_name': user.last_name, 'email': user.email}
  redis_connect.set(token, json.dumps(_dict), 259200)  # 存redis 259200秒=72個小時
  return Response(data={'status_code': 200, 'msg': '登錄成功!', 'token': token})
 return Response(data={'status_code': 403, 'msg': '密碼錯誤!'})

3.3 登錄后redis存儲的用戶記錄

4. 重寫認證token方法

4.1 源碼分析

我們可以全局搜索TokenAuthentication 找到【restframework】源碼中的Token認證類

這個類中我們只需要關(guān)注authenticate_credentials這個方法就可以了。

 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)

源碼首先通過接口請求的token (源碼中的key) 去數(shù)據(jù)庫中尋找是否有該對應(yīng)的記錄
如果有則認證成功返回usertoken這兩個模型對象

如果沒有對應(yīng)的記錄,則拋出【invalid token】異常

  try:
token = model.objects.select_related('user').get(key=key)
  except model.DoesNotExist:
raise exceptions.AuthenticationFailed(_('Invalid token.'))

如果有對應(yīng)的記錄,但用戶是未激活的 (is_active=0) 則拋出【User inactive or deleted】異常

if not token.user.is_active:
raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

然后restframework會在視圖層的dispatch方法中進行異常的封裝并返回響應(yīng)結(jié)果。

4.2 進行重寫

經(jīng)過源碼分析,我們需要重寫的有兩部分:

1.驗證token (源碼中的key) 是否有效,之前是從數(shù)據(jù)庫進行驗證的現(xiàn)在需要通過redis去驗證

2.重新封裝user模型對象,但有個問題需要注意的是:
如果你重寫了django的user對象,讓它關(guān)聯(lián)了其他表的屬性,那么這里則不能將其封裝進user這個對象的,因為redis不能存儲一個對象!,當然如果非要這么做可以將外鍵id值在登錄 (寫入token) 的時候存入redis,然后在這里通過該外鍵id去查詢關(guān)聯(lián)的外鍵表獲取屬性,再封裝到user模型對象中!

重寫后的代碼

class RedisTokenAuthentication(TokenAuthentication):
 def authenticate_credentials(self, key):
  null = None  # json的None為null,所以需要定義一下
  user_data = redis_connect.get(key)
  if user_data:
user_dict = json.loads(user_data)
user_obj = User()
for key_name in user_dict.keys():
 setattr(user_obj, key_name, user_dict[key_name])
return user_obj, key
  raise exceptions.AuthenticationFailed(_('無效的token.'))

4.3 加入認證配置

settings.py配置文件中,加入如下配置

REST_FRAMEWORK = {
 'DEFAULT_AUTHENTICATION_CLASSES': (  #如果有REST_FRAMEWORK配置項了單獨加入該項即可
  'Demo.RedisAuthentication.RedisTokenAuthentication',  # 項目名稱.重新認證類所在的文件.類名
 ),
}

4.4 效果展示

增加一個接口

path('test-token', views.test_token),

接口方法代碼

@api_view(['GET'])
@permission_classes((permissions.IsAuthenticated,))
def test_token(request):
 """
 測試token
 """
 print('登錄的用戶名是:', request.user)
 res_data = {'data': {'status_code': 200}}
 return Response(**res_data)

輸出結(jié)果

登錄的用戶名是: admin

三、總結(jié)

無論是django還是restframework,他們的源碼和官方文檔在我看來是非常清晰的 (在我看的那么多官方文檔中算很清晰的了) 這里給DRF的團隊點個贊??!!

到此這篇關(guān)于django restframework使用redis實現(xiàn)token認證的文章就介紹到這了,更多相關(guān)django restframework token認證內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

版權(quán)聲明:本站文章來源標注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部