Django restframework Token擁有不過期的認證


REST框架中的Token認證不像Session認證一樣,它是沒有辦法設置過期時間的,但是有時我們需要對Token做過期驗證,比如說用戶在A設備登陸之后獲取一個Token,如果用戶在沒有清空瀏覽器緩存的情況下,Token將一直保存在緩存中,一周后在訪問依舊有效,但我們並不希望這樣,我們覺得Token認證應該和Session一樣都有過期時間,過期之后作廢。

  1. 首先,看下TokenAuthentication模塊的源碼如下:

     class TokenAuthentication(BaseAuthentication):
         keyword = 'Token'
         model = None
     
         def get_model(self):
             if self.model is not None:
                 return self.model
             from rest_framework.authtoken.models import Token
             return Token
     
         def authenticate(self, request):
             auth = get_authorization_header(request).split()
     
             if not auth or auth[0].lower() != self.keyword.lower().encode():
                 return None
     
             if 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):    # key=前端在請求頭傳過來的Token
             model = self.get_model()     # 獲取Token模塊
             try:
                 token = model.objects.select_related('user').get(key=key)   # 通過key獲取Token
             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.keyword  # 然后把Token和登錄的用戶返回給View
    

上面有注解的地方是關鍵。 過期驗證,就相當於多加一個判斷,只要繼承該類,然后重寫authenticate_credentials方法即可。以下是我實現的例子,以expiringTokenAuthentication.py保存。

from rest_framework.authentication import TokenAuthentication
from django.utils.translation import ugettext_lazy as _
from rest_framework import exceptions
from django.utils import timezone
from datetime import timedelta
from django.conf import settings
class ExpiringTokenAuthentication(TokenAuthentication):
    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.'))
		
		if timezone.now() > (token.created + timedelta(DAYS)):  # 重點就在這句了,這里做了一個Token過期的驗證,如果當前的時間大於Token創建時間+DAYS天,那么久返回Token已經過期
        raise exceptions.AuthenticationFailed(_('Token has expired'))
    return (token.user, token)

以此類推, 要對token進行類似的判斷,都可以按上面的代碼進行仿寫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM