日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

状态保持与身份认证

發布時間:2024/1/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 状态保持与身份认证 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 關系

1.1 緩存

Cookie和Session
提示:
Cookie和Session是Django程序中用來緩存數據的
狀態保持和Cookie、Session的關系
提示:
* 容易出現的誤解:狀態保持就是Cookie和Session,Cookie和Session就是狀態保持。
* 狀態保持和Cookie、Session是兩種不同的概念,需要區分開,不能混淆。
狀態保持

* 用于記錄當前用戶的狀態,比如,用戶登錄后記錄登錄的狀態。

Cookie、Session:

* Cookie、Session僅僅是Django提供的緩存機制而已,用于緩存數據的。 * 比如:* Cookie和Session緩存購物車數據* Cookie和Session緩存用戶登錄狀態 (狀態保持)

狀態保持和Cookie、Session的關系

* Cookie和Session僅僅是狀態保持的一種實現方式而已 * 而能夠實現狀態保持的方式不僅僅只有Cookie和Session,比如JWT也可以實現狀態保持

1.2 應用場景

1.1 登錄接口實現的業務邏輯

在整個登錄接口實現中,除了檢查用戶名和密碼以外,我們需要通過某種方式來記住用戶身份(狀態保持),還有用戶認證。
1.2 用戶下次訪問不用登錄

例如,在我們登錄boss直聘網站后,我們可以不用再次登錄就可以直接使用網站,并且網站上有我們的信息

2. cookie

2.1 簡介

需求:

  • HTTP協議本身是無狀態的,即服務器無法判斷用戶身份。

問題:
服務器默認是無法識別當前登錄用戶是誰的,即無法記住登錄狀態。

解決:

  • Cookie
  • 我們可以使用Cookie機制記住用戶的登錄狀態

1. 定義

  • Cookie,最早是網景公司的前雇員 Lou Montulli 在 1993 年 3 月發明的。
  • Cookie,指某些網站為了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據(通常經過加密)。
  • cookie 是一個實際存在的東西,是http協議中定義header中的字段,實際上是一小段存儲在用戶瀏覽器中的文本信息

2. 具體位置

  • 在瀏覽器左上角的感嘆號或者鎖
  • 在檢查模式的Application中的Storage里,其中LocalStorage存儲永久cookie,SessionStorage存儲臨時cookie

2.2 機制

  • 客戶端向服務器發起請求,如果服務器需要記錄該用戶狀態,就通過響應向客戶端瀏覽器頒發一個Cookie。
    • 該Cookie中需要包含用戶的唯一標識信息
  • 客戶端瀏覽器會把Cookie保存起來。
  • 當瀏覽器再次請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。
  • 服務器檢查該Cookie,以此來辨認用戶狀態。

2.3 特點

  • Cookie,以鍵值對Key-Value形式進行信息的存儲
  • Cookie,基于域名安全,不同域名的Cookie是不能互相訪問的
    • 例如: 保存在www.baidu.com域名下面的Cookie是不能被其他域名訪問的
  • Cookie,它會自動跟隨當前的請求傳遞到對應域名所在的服務器中。

2.4 操作

1. 設置Cookie

  • 可以通過**HttpResponse()**對象中的set_cookie()方法來設置Cookie。
# 創建響應對象 response = HttpResponse()# 使用響應對象設置Cookie response.set_cookie(key, value, max_age=cookie有效期)
  • 響應對象:常見的構造響應對象的方式
    • HttpResponse():響應多種數據類型
    • JsonResponse():響應JSON
    • redirect():重定向
    • render():渲染并響應HTML模板
  • max_age:單位為秒,默認為None
    • 如果是臨時Cookie,可將max_age設置為None。
    • 如果是有具體有效期的Cookie,可將max_age設置為具體的秒數。
class BooksView(View):"""測試模板http://127.0.0.1:8000/books/"""def get(self, request):# 查詢所有圖書信息books = BookInfo.objects.all()# 構造上下文context = {'books': books}# 使用上下文渲染'book.html',并返回給客戶端response = render(request, 'books.html', context)# 設置Cookieresponse.set_cookie('name', 'itcast', max_age=None)# 響應結果,并寫Cookie到瀏覽器return response

2. 讀取Cookie

  • 可以通過HttpRequest對象的COOKIES屬性來讀取本次請求攜帶的cookie值。
class TestCookieView(View):"""測試Cookiehttp://127.0.0.1:8000/cookies/"""def get(self, request):# 讀取Cookiename = request.COOKIES.get('name')print(name)return http.HttpResponse('測試Cookie')

3. session

3.1 簡介

需求:
Cookie中存儲敏感信息是否安全?
結論:

如果存儲前做加密處理,就會是安全的,但是加密后的敏感信息依然會暴露在瀏覽器中

思考:
有沒有一種方式可以將某些敏感數據存儲的更加安全些,即加密又不會暴露出去?
解決:

  • Session

1. 定義

  • 原來session是會話的英文,是一個抽象概念,是開發者為了實現中斷和繼續等操作,將usergent和server之間一對一的交互,抽象為“會話狀態”。
  • 現在的session是為了繞開cookie本身和后端存儲實現的一種更高級的會話狀態實現,概念上cookie和session可以認為是同一層次的概念,也可以是不同層次的概念,具體到實現上session存在是因為sessionID的存在,通常要借助cookie實現,但這并非必要,只能說是通用性較好的一種實現方案
  • 也可以cookie看做一對鍵值對,cookie是session的key,有cookie里的sessionID才能取到用戶信息
  • Session,是一種會話控制方式。由服務端創建,并且保存在服務端的數據存儲形式。
  • Session,內部也是以key-value 鍵值對的形式存儲數據。
  • Session,有些內容會被加密,所以可以存儲敏感信息。
  • 處理Session數據的子應用:

    處理Session的中間件:

    PS:如需禁用Session,將上圖中的session中間件注釋掉即可。

3.2 機制

  • 客戶端向服務器發起請求,如果服務器需要記錄該用戶狀態,就可以通過Session在服務端將該用戶的唯一標識信息存儲起來。
    • session_key:一個隨機的唯一的不重復的字符串
    • session_data:用戶的唯一標識信息(密文)
  • 然后,服務端會向客戶端瀏覽器頒發一個Cookie。
    • 該Cookie中包含了Session存儲數據時使用的那個session_key
      該Cookie的具體形式為:'sessionid': 'session_key'
  • 當瀏覽器再次請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。
  • 服務器提取該Cookie中的session_key,再使用它提取session_data。
  • 最后使用session_data來辨認用戶狀態

3.3 特點

  • 存儲敏感、重要的信息
    • 因為session數據是存儲在服務端的,不會直接暴露給用戶
  • 相比較Cookie可以存儲更多的內容
    • 不同的瀏覽器,對Cookie都有不同的數量和大小的限制
  • 依賴于Cookie
    • 因為session_key需要存儲在Cookie中
  • Session共享
    • 利用獨立部署的session服務器(集群)統一管理Session,服務器每次讀寫Session時,都訪問Session服務器。

3.4 cookie和session關系

  • 注意:
    • 但是兩個獨立的東西,即sessionID雖然存儲在cookie中,但絕不依賴cookie
  • 綜合考慮
    • 把重要信息存儲在session,用戶名和sessionID可以放在cookie中
    • 利用時效機制,給cookie設置有效期,比如十四天,然后讓用戶十四天再登錄
    • 可以設置sesssionID傳入方式,若有其他方式傳入sessinID,cookie完全可以禁用

3.5 操作

1. 設置Session

可以通過 HttpRequest() 對象中的session屬性來設置Session。

request.session['key'] = value class BooksView(View):"""測試模板http://127.0.0.1:8000/books/"""def get(self, request):# 查詢所有圖書信息books = BookInfo.objects.all()# 構造上下文context = {'books': books}# 使用上下文渲染'book.html',并返回給客戶端response = render(request, 'books.html', context)# 設置Cookieresponse.set_cookie('name', 'itcast', max_age=3600)# 設置Sessionrequest.session['name'] = 'itcast'# 響應結果,并寫Cookie到瀏覽器return response

2. 讀取Session

根據鍵讀取值

request.session.get('key', 默認值) class TestSessionView(View):"""測試Sessionhttp://127.0.0.1:8000/session/"""def get(self, request):# 讀取Sessionname = request.session.get('name')print(name)return http.HttpResponse('測試Session')

3. 操作Session的其他方式

清除所有Session,在存儲中刪除值部分。

request.session.clear()

清除session數據,在存儲中刪除session的整條數據。

request.session.flush()

刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值。

del request.session['key']

設置session的有效期

request.session.set_expiry(value)
  • 如果value是一個整數,session將在value秒沒有活動后過期。
  • 如果value為0,那么用戶session的Cookie將在用戶的瀏覽器關閉時過期。
  • 如果value為None,那么session有效期將采用系統默認值,默認為兩周。
    • 可以通過在settings.py中設置SESSION_COOKIE_AGE來設置全局默認值。

3.6 Session數據存儲的位置

1. 默認的存儲位置

Session數據默認存儲的位置是在settings.py的DATABASES配置項指定的SQL數據庫中

  • 因為Session引擎默認的配置為:
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
  • 數據庫中的表如圖所示

  • 表結構如下

由表結構可知,操作Session包括三個數據:鍵,值,過期時間。

2. 本地緩存

存儲在本機內存中,如果丟失則不能找回,比數據庫的方式讀寫更快。

SESSION_ENGINE='django.contrib.sessions.backends.cache'

3. 混合存儲

優先從本機內存中存取,如果沒有則從數據庫中存取。

SESSION_ENGINE='django.contrib.sessions.backends.cached_db'

4. Redis

在Redis中保存Session,需要引入第三方擴展,我們可以使用django-redis來解決。

1)安裝擴展

pip install django-redis

2)配置

在settings.py文件中做如下設置

CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379/1","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}} } SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default"

3. JWT

3.1 JWT簡介

1. Json Web Token(JWT)

  • JSON Web Token(JWT)是一個非常輕巧的規范。這個規范允許我們使用JWT在兩個組織之間傳遞安全可靠的信息。

官方定義:JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties



JWT是一個有著簡單的統一表達形式的字符串:

2. JWT組成/token格式

  • JWT組成,也可以說是token格式,是有header,payload,signature三部分以點分割的字符串
  • jwt技術特性
  • 服務器簽發,頒發(交)給客戶端保存;
  • 令牌(token)中記錄了用戶身份信息;
  • 令牌(token)可以被驗證出真偽(有效性可以被校驗出來);
  • 單點登錄

    客戶端在某一臺服務器(授權中心)完成登錄授權,拿到token之后,可以憑借token(令牌)在任意其他服務器中完成身份驗證;

    2.1 頭部(Header)

    頭部用于描述關于該JWT的最基本的信息,例如其類型以及簽名所用的算法等。

    • JSON內容要經Base64 編碼生成字符串成為Header。
    • 頭部(header):typ(類型說明)和alg(加密方法)

    作用:轉化:

  • 把header字典轉化為json
  • header = json.dumps(header)
  • 再把json格式的頭信息通過base64比愛你嗎得出最終的頭信息字符串
  • herder = base64.b64(header.encode()).decode() print("header:", header)

    2.2 載荷(PayLoad)

    payload的五個字段都是由JWT的標準所定義的。
    1. iss: 該JWT的簽發者
    2. sub: 該JWT所面向的用戶
    3. aud: 接收該JWT的一方
    4. exp(expires): 什么時候過期,這里是一個Unix時間戳
    5. iat(issued at): 在什么時候簽發的

    • JSON內容要經Base64 編碼生成字符串成為PayLoad。

    作用:存儲用戶信息

    payload = json.dumps(payload) payload = base64.b64encode.encode().decode() print("payload:", payload)

    2.3 簽名(signature)

    • 這個部分header與payload通過header中聲明的加密方式,使用密鑰secret進行加密,生成簽名。 JWS的主要目的是保證了數據在傳輸過程中不被修改,驗證數據的完整性。但由于僅采用Base64對消息內容編碼,因此不保證數據的不可泄露性。所以不適合用于傳輸敏感數據。

    作用:校驗token真偽

    使用哈希算法對信息進行摘要生成簽名,目的是保證信息的可靠性;

    原理:只要信息沒有改動,那么原信息和簽名是匹配的

    3、token簽發

    簽發

    import hmac, hashlib # hmac:Python的一個用于hash(簽名,散列)運算的模塊 hashlib:專門實現具體的算法# 1、構建哈希對象 # key: 加密使用的秘鑰--生成簽名 # msg: header和payload信息 # digestmod: 算法 key = "eerewrwerwrwewrwegegsf" SECRET_KEY = '' message = header + '.' + payload h_obj = hmac.new(key = SECRET_KEY.encode(), msg=message.encode(), djgestmod=hashlib.sha256) # 2、找對象里的方法,生成簽名 signature = b_obj.hexdigest() print("signature:", signature) ======================= JWT_TOKEN = header + '.' + signature print("token",JWT_TOKEN) =======================

    4、token校驗

    核心原理:重新對header和payload按照簽發時相同的秘鑰和算法加密

    # 模擬前端傳參 token_from_browser = JWT_TOKEN # 有效 token_from_browser = 'fdds' + JWT_TOKEN # 篡改# 模擬校驗原理 # 原理:只要信息沒有改動,那么原信息和簽名是匹配的 # 只要信息沒有被篡改,那么根據相同而秘鑰和算法,生成的第三部分簽名和原來的簽名一定一致# 1、獲取信息(header和payload) old_header = token_from_browser.split('.',[0]) old_payload = token_from_brower.split('.',[1]) old_signature = token_from_brower.split('.'[2]) # 2、把信息按照相同的秘鑰和算法,重新生成新的簽名 message = old_header + '.' +old_payload new_h_obj = hmac.new(key=SECRET.KEY.encode(), msg=message.encode(), digestmod=hashlib.sha256) new_signature = new_h_obj.hexdigest() print("新的簽名:", new_signature) # 3、比對新舊簽名是否一致:一致則信息沒有被篡改,否則信息就被篡改了 if old_signature = new_signature:print("驗證成功")# 提取用戶數據user_json = base64.b64decode(old_payload.encode().decode())user_dict = json.loads(user_json)print("解析出來的用戶身份信息:", user_dict) else:print("驗證失敗")

    4. PythonLib

    4.1 JWT的Python庫

    • 獨立的JWT Python庫
    • itsdangerous
      • JSONWebSignatureSerializer
      • TimedJSONWebSignatureSerializer (可設置有效期)
    • pyjwt
      https://pyjwt.readthedocs.io/en/latest/

    4.2 安裝

    $ pip install pyjwt

    4.3 用例

    >>> import jwt>>> encoded_jwt = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256')>>> encoded_jwt'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg'>>> jwt.decode(encoded_jwt, 'secret', algorithms=['HS256']){'some': 'payload'} import jwt from flask import current_appdef generate_jwt(payload, expiry, secret=None):"""生成jwt:param payload: dict 載荷:param expiry: datetime 有效期:param secret: 密鑰:return: jwt"""_payload = {'exp': expiry}_payload.update(payload)if not secret:secret = current_app.config['JWT_SECRET']token = jwt.encode(_payload, secret, algorithm='HS256')return token.decode()def verify_jwt(token, secret=None):"""檢驗jwt:param token: jwt:param secret: 密鑰:return: dict: payload"""if not secret:secret = current_app.config['JWT_SECRET']try:payload = jwt.decode(token, secret, algorithm=['HS256'])except jwt.PyJWTError:payload = Nonereturn payload

    5. 實施方案

    5.1 需求

    • 設置有效期,但有效期不宜過長,需要刷新。如何解決刷新問題?
    • 手機號+驗證碼(或帳號+密碼)驗證后頒發接口調用token與refresh_token(刷新token)
    • Token 有效期為2小時,在調用接口時攜帶,每2小時刷新一次
    • 提供refresh_token,refresh_token 有效期14天
    • 在接口調用token過期后憑借refresh_token 獲取新token
    • 未攜帶token 、錯誤的token或接口調用token過期,返回401狀態碼
    • refresh_token 過期返回403狀態碼,前端在使用refresh_token請求新token時遇到403狀態碼則進入用戶登錄界面從新認證。
    • token的攜帶方式是在請求頭中使用如下格式:
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
    • 注意:Bearer前綴與token中間有一個空格

    5.2 實現

    1. 注冊或登錄獲取token

    # toutiao/resources/user/passport.pty class AuthorizationResource(Resource):"""認證"""def _generate_tokens(self, user_id, with_refresh_token=True):"""生成token 和refresh_token:param user_id: 用戶id:return: token, refresh_token"""# 頒發JWTnow = datetime.utcnow()expiry = now + timedelta(hours=current_app.config['JWT_EXPIRY_HOURS'])token = generate_jwt({'user_id': user_id, 'refresh': False}, expiry)refresh_token = Noneif with_refresh_token:refresh_expiry = now + timedelta(days=current_app.config['JWT_REFRESH_DAYS'])refresh_token = generate_jwt({'user_id': user_id, 'refresh': True}, refresh_expiry)return token, refresh_tokendef post(self):"""登錄創建token"""json_parser = RequestParser()json_parser.add_argument('mobile', type=parser.mobile, required=True, location='json')json_parser.add_argument('code', type=parser.regex(r'^\d{6}$'), required=True, location='json')args = json_parser.parse_args()mobile = args.mobilecode = args.code# 從redis中獲取驗證碼key = 'app:code:{}'.format(mobile)try:real_code = current_app.redis_master.get(key)except ConnectionError as e:current_app.logger.error(e)real_code = current_app.redis_slave.get(key)try:current_app.redis_master.delete(key)except ConnectionError as e:current_app.logger.error(e)if not real_code or real_code.decode() != code:return {'message': 'Invalid code.'}, 400# 查詢或保存用戶user = User.query.filter_by(mobile=mobile).first()if user is None:# 用戶不存在,注冊用戶user_id = current_app.id_worker.get_id()user = User(id=user_id, mobile=mobile, name=mobile, last_login=datetime.now())db.session.add(user)profile = UserProfile(id=user.id)db.session.add(profile)db.session.commit()else:if user.status == User.STATUS.DISABLE:return {'message': 'Invalid user.'}, 403token, refresh_token = self._generate_tokens(user.id)return {'token': token, 'refresh_token': refresh_token}, 201

    2. 請求鉤子

    # common/utils/middlewares.py from flask import request, g from .jwt_util import verify_jwtdef jwt_authentication():"""根據jwt驗證用戶身份"""g.user_id = Noneg.is_refresh_token = Falseauthorization = request.headers.get('Authorization')if authorization and authorization.startswith('Bearer '):token = authorization.strip()[7:]payload = verify_jwt(token)if payload:g.user_id = payload.get('user_id')g.is_refresh_token = payload.get('refresh')

    3. 強制登錄裝飾器

    # common/utils/decorators.py def login_required(func):"""用戶必須登錄裝飾器使用方法:放在method_decorators中"""@wraps(func)def wrapper(*args, **kwargs):if not g.user_id:return {'message': 'User must be authorized.'}, 401elif g.is_refresh_token:return {'message': 'Do not use refresh token.'}, 403else:return func(*args, **kwargs)return wrapper

    4. 更新token接口

    # toutiao/resources/user/passport.py class AuthorizationResource(Resource):"""認證"""...# 補充put方式 更新token接口def put(self):"""刷新token"""user_id = g.user_idif user_id and g.is_refresh_token:token, refresh_token = self._generate_tokens(user_id, with_refresh_token=False)return {'token': token}, 201else:return {'message': 'Wrong refresh token.'}, 403

    6. 禁用問題

    6.1 需求

    • token頒發給用戶后,在有效期內服務端都會認可,但是如果在token的有效期內需要讓token失效,該怎么辦?
    • 此問題的應用場景:
      • 用戶修改密碼,需要頒發新的token,禁用還在有效期內的老token
      • 后臺封禁用戶
    • 偽代碼思路如下:
      在redis中使用set類型保存新生成的token
    key = 'user:{}:token'.format(user_id) pl = redis_client.pipeline() pl.sadd(key, new_token) pl.expire(key, token有效期) pl.execute()

    • 客戶端使用token進行請求時,如果驗證token通過,則從redis中判斷是否存在該用戶的user:{}:token記錄:
      • 若不存在記錄,放行,進入視圖進行業務處理
      • 若存在,則對比本次請求的token是否在redis保存的set中:
        • 若存在,則放行
        • 若不在set的數值中,則返回403狀態碼,不再處理業務邏輯
    key = 'user:{}:token'.format(user_id) valid_tokens = redis_client.smembers(key)# 若上傳的token不在白名單列表valid_tokens內,返回403要求重新登錄 if valid_tokens and token not in valid_tokens:return {'message': 'Invalid token'.}, 403

    說明:
    1. redis記錄設置有效期的時長是一個token的有效期,保證舊token過期后,redis的記錄也能自動清除,不占用空間。
    2. 使用set保存新token的原因是,考慮到用戶可能在舊token的有效期內,在其他多個設備進行了登錄,需要生成多個新token,這些新token都要保存下來,既保證新token都能正常登錄,又能保證舊token被禁用

    6.2 具體代碼實現

    1. 修改密碼接口

    class ModifyPasswordResource(Resource):# 修改密碼要求用戶必須登錄method_decorators = [login_required]def post(self):"""修改密碼邏輯"""# 1.獲取用戶iduser_id = g.user_id# 2.保存到redis中的keykey = 'user:{}:token'.format(user_id)# 3.獲取管道對象pl = current_app.redis_master.pipeline()# 4.先刪除已有的白名單if pl.exists(key):pl.delete(key)# 5.生成新的token值new_token, refresh_token = self._generate_tokens(user_id)# 6.sadd 往集合中添加成員--添加修改密碼后的新的token值pl.sadd(key, new_token)# 7.設置2小時有效期pl.expire(key, 7200)# 8.設置修改密碼的標志位,同時設置2小時有效期modify_key = "modify:{}".format(user_id)pl.setex(modify_key, 7200, "modify")# 9.執行管道pl.execute()# 10.修改密碼成功,并返回新的token值return {"message": "修改密碼成功", "valid_token": new_token}

    2. 在middleware 的def jwt_authorization():方法中補充驗證白名單的邏輯

    def jwt_authorization():"""每次請求之前進行jwt驗證:return:"""# 請求頭Header攜帶# {Authorization: "Bearer jwt_token"}# 默認值g.user_id = Noneg.is_refresh = False# 1.提取請求頭中的token數據header_token = request.headers.get("Authorization")# 2.截取真正的jwt-token值if header_token is not None and header_token.startswith("Bearer "):jwt_token = header_token[7:]# 3.jwttoken的校驗 --- 如果token沒有值 或者過期了 自動會拋出401異常payload = verify_jwt(token=jwt_token)# 4.獲取載荷中的用戶信息,使用g對象存儲用戶信息if payload is not None:g.user_id = payload.get("user_id")g.is_refresh = payload.get("is_refresh", False)# ========================【白名單驗證邏輯】================================if g.user_id:# 根據key獲取是否進行過密碼修改的標志位modify_key = "modify:{}".format(g.user_id)modify = current_app.redis_master.get(modify_key)# 如果是修改過密碼,同時又不是刷新token,需要進行白名單認證if modify == 'modify' and g.is_refresh is False:# 白名單認證ret = white_list()# 如果認證結果為False 代表token沒有在白名單內部if ret is False:return "token is not in white list", 403

    3. 判斷用戶上傳的token是否在白名單列表中

    def white_list():"""判斷用戶上傳的token是否在白名單列表中如果在:正常訪問如果不在:攔截不讓訪問視圖函數,需要使用修改密碼后生成的最新的token才能訪問:return: BooL值 False代表token沒有在白名單內部"""# 用戶iduser_id = g.user_idkey = 'user:{}:token'.format(user_id)# 獲取白名單內部的token# smembers 獲取集合中的成員valid_tokens = current_app.redis_master.smembers(key)# set類型數據 裝的bytes類型數據print(type(valid_tokens))# 把set、轉換成python的列表valid_tokens = list(valid_tokens)# 提取前端發送的tokenheader_token = request.headers.get("Authorization")token = header_token[7:]# 判斷前端發送的token值是否在白名單列表中,如果不在返回403 重新登錄if valid_tokens and token not in valid_tokens:return Falseelse:return True

    6.3 思路流程圖

    總結

    以上是生活随笔為你收集整理的状态保持与身份认证的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。