中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

flask session組件的使用示例

發布時間:2020-09-25 22:14:08 來源:腳本之家 閱讀:149 作者:W-D 欄目:開發技術

一、簡介

flask中session組件可分為內置的session組件還有第三方flask-session組件,內置的session組件功能單一,而第三方的flask-sessoin可支持redis、memcached、文件等進行session的存儲。以下將介紹內置session以及第三方session組件的使用方法以及處理機制。

二、內置session處理機制

Cookie與Session

Cookie:

Cookie意為“甜餅”,是由W3C組織提出,最早由Netscape社區發展的一種機制。目前Cookie已經成為標準,所有的主流瀏覽器如IE、Netscape、Firefox、Opera等都支持Cookie。由于HTTP是一種無狀態的協議,服務器單從網絡連接上無從知道客戶身份。怎么辦呢?就給客戶端們頒發一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務器就能從通行證上確認客戶身份了。這就是Cookie的工作原理。

Cookie實際上是一小段的文本信息。客戶端請求服務器,如果服務器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還可以根據需要修改Cookie的內容

Session:

Session是另一種記錄客戶狀態的機制,不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務器上。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上。這就是Session。客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態就可以了,實質上session就是保存在服務器端的鍵值對。

如果說Cookie機制是通過檢查客戶身上的“通行證”來確定客戶身份的話,那么Session機制就是通過檢查服務器上的“客戶明細表”來確認客戶身份。Session相當于程序在服務器上建立的一份客戶檔案,客戶來訪的時候只需要查詢客戶檔案表就可以了。

第一次請求,session的創建過程

在flask上下文中介紹了,請求到flask框架會執行wsgi_app方法:

def wsgi_app(self, environ, start_response):
 ctx = self.request_context(environ) #實例化生成RequestContext對象
 error = None 
 try:
  try:
   ctx.push() #push上下文到LocalStack中
   response = self.full_dispatch_request() #執行視圖函數過程
  except Exception as e:
   error = e
   response = self.handle_exception(e) #處理異常
  except:
   error = sys.exc_info()[1]
   raise
  return response(environ, start_response)
 finally:
  if self.should_ignore_error(error):
   error = None
  ctx.auto_pop(error)  # 刪除LocalStack中的數據

在改方法中會生成一個ctx也就是RequestContext對象:

class RequestContext(object):
 def __init__(self, app, environ, request=None):
  self.app = app # app對象
  if request is None:
   request = app.request_class(environ) 
  self.request = request # 封裝request
  self.url_adapter = app.create_url_adapter(self.request)
  self.flashes = None
  self.session = None #一開始的session

在這個對象中封裝了session,最初為None。接著在wsgi_app中執行ctx.push:

def push(self):
  app_ctx = _app_ctx_stack.top # 獲取app上下文
  if app_ctx is None or app_ctx.app != self.app:
   app_ctx = self.app.app_context() #將app上下文push到app_ctx對于的LocalStack中
   app_ctx.push()
   self._implicit_app_ctx_stack.append(app_ctx)
  else:
   self._implicit_app_ctx_stack.append(None)
  if hasattr(sys, 'exc_clear'):
   sys.exc_clear()
  _request_ctx_stack.push(self)
  if self.session is None: # 判斷session是否為None,一開始為None
   session_interface = self.app.session_interface # 獲取操作session的對象
   self.session = session_interface.open_session( #調用open_session 創建session
    self.app, self.request
   )
   if self.session is None:
    self.session = session_interface.make_null_session(self.app)

這里我們主要關注session,前面的代碼在上下文中已經進行了相關說明,這里有個判斷session是否為None,剛開始RequestContext中的session為None,所以條件成立,此時執行以下語句:

session_interface = self.app.session_interface
self.session = session_interface.open_session(
    self.app, self.request
   )
if self.session is None:
 self.session = session_interface.make_null_session(self.app)

首先來看session_interface = self.app.session_interface,self.app.session_interface就是app中的session_interface屬性:

session_interface = SecureCookieSessionInterface()

默認是一個SecureCookieSessionInterface()對象,該對象的內部主要實現了open_session和save_session用于使用和保存session。接著self.session被重新賦值為session_interface.open_session(self.app, self.request)方法返回的值,以下為open_session源碼:

def open_session(self, app, request):
 s = self.get_signing_serializer(app) #根據app.secret_key獲取簽名算法
 if s is None:
  return None
 # 根據配置中的session_cookie_name獲取session對于的值
 val = request.cookies.get(app.session_cookie_name) #如果request.cookies為空,val為空
 if not val:
  return self.session_class()
 max_age = total_seconds(app.permanent_session_lifetime)    
 try:
  data = s.loads(val, max_age=max_age)
  return self.session_class(data)
 except BadSignature:
  return self.session_class()

該方法返回self.session_class(),當請求第一次來時,request.cookies為None,所以val也為None,返回self.session_class(),而session_class又是SecureCookieSession:

session_class = SecureCookieSession

所以我們繼續看SecureCookieSession:

class SecureCookieSession(CallbackDict, SessionMixin):
 accessed = False

 def __init__(self, initial=None):
  def on_update(self):
   self.modified = True
   self.accessed = True

  super(SecureCookieSession, self).__init__(initial, on_update)

 def __getitem__(self, key):
  self.accessed = True
  return super(SecureCookieSession, self).__getitem__(key)

 def get(self, key, default=None):
  self.accessed = True
  return super(SecureCookieSession, self).get(key, default)

 def setdefault(self, key, default=None):
  self.accessed = True
  return super(SecureCookieSession, self).setdefault(key, default)

該類繼承了CallbackDict, SessionMixin我們繼續來看看CallbackDict:

class CallbackDict(UpdateDictMixin, dict):

 """A dict that calls a function passed every time something is changed.
 The function is passed the dict instance.
 """

 def __init__(self, initial=None, on_update=None):
  dict.__init__(self, initial or ())
  self.on_update = on_update

 def __repr__(self):
  return '<%s %s>' % (
   self.__class__.__name__,
   dict.__repr__(self)
  )

也就是說SecureCookieSession繼承了CallbackDict而CallbackDict繼承了原生的dict,所以我們可以認為SecureCookieSession是一個特殊的字典,是調用了SecureCookieSessionInterface類中open_session返回的特殊字典,經過進一步分析self.session此時就是這個字典,這也意味著session在執行open_session方法時候被創建了,并保存在ctx中,也就是在RequestContext對象中,當我們使用session時候是通過全局變量session = LocalProxy(partial(_lookup_req_object, 'session'))由LocalProxy對象從ctx中獲取到session。

第二次請求

開始我們知道session第一次請求來的時候是在open_session方法之后被創建,當第二次請求時,此時在open_session方法中,val已經不在是None,此時獲取cookie的有效時長,如果cookie依然有效,通過與寫入時同樣的簽名算法將cookie中的值解密出來并寫入字典并返回,若cookie已經失效,則仍然返回'空字典',這樣以來在第二次請求中就能獲取到之前保存的session數據。

session生命周期

我們介紹了session創建時候是在ctx.push時候開始創建,也就是說在這之后我們就可以使用session,對它進行操作了,那么session什么時候保存呢?我們接下來繼續看wsgi_app:

def wsgi_app(self, environ, start_response):
 ctx = self.request_context(environ)
 error = None
 try:
  try:
   ctx.push()
   response = self.full_dispatch_request()
  except Exception as e:
   error = e
   response = self.handle_exception(e)
  except:
   error = sys.exc_info()[1]
   raise
  return response(environ, start_response)
 finally:
  if self.should_ignore_error(error):
   error = None
  ctx.auto_pop(error)

生成session后,接著執行self.full_dispatch_request():

def full_dispatch_request(self):
 """Dispatches the request and on top of that performs request
 pre and postprocessing as well as HTTP exception catching and
 error handling.

 .. versionadded:: 0.7
 """
 self.try_trigger_before_first_request_functions() #執行app.before_first_reques鉤子函數
 try:
  request_started.send(self) # 觸發request_started信號
  rv = self.preprocess_request() # 執行before_request鉤子函數
  if rv is None:
   rv = self.dispatch_request() # 執行視圖函數
 except Exception as e:
  rv = self.handle_user_exception(e)
 return self.finalize_request(rv)

這一部分先執行鉤子app.before_first_reques在觸發request_started信號,再執行before_request鉤子函數,然后在執行視圖函數,rv是執行完視圖函數的返回值,最后執行finalize_request,這里的session保存就發生在這里:

def finalize_request(self, rv, from_error_handler=False):
 response = self.make_response(rv)
 try:
  response = self.process_response(response)
  request_finished.send(self, response=response)
 except Exception:
  if not from_error_handler:
   raise
  self.logger.exception('Request finalizing failed with an '
        'error while handling an error')
 return response

注意這里的在最后會session判斷是否為空,會執行save_session方法,也就是SecureCookieSessionInterface的save_session方法:

def save_session(self, app, session, response):
 domain = self.get_cookie_domain(app)
 path = self.get_cookie_path(app)

 # If the session is modified to be empty, remove the cookie.
 # If the session is empty, return without setting the cookie.
 if not session:
  if session.modified:
   response.delete_cookie(
    app.session_cookie_name,
    domain=domain,
    path=path
   )

  return

 # Add a "Vary: Cookie" header if the session was accessed at all.
 if session.accessed:
  response.vary.add('Cookie')

 if not self.should_set_cookie(app, session):
  return

 httponly = self.get_cookie_httponly(app)
 secure = self.get_cookie_secure(app)
 samesite = self.get_cookie_samesite(app)
 expires = self.get_expiration_time(app, session)
 val = self.get_signing_serializer(app).dumps(dict(session))
 response.set_cookie(
  app.session_cookie_name,
  val,
  expires=expires,
  httponly=httponly,
  domain=domain,
  path=path,
  secure=secure,
  samesite=samesite
 )

該方法最后保存的session調用的response.set_cookie,其實是將數據保存在cookie中,也就是在客戶端的瀏覽器中,并非在服務端進行數據的保存,當請求完畢后會執行ctx.auto_pop(error)這時候會從上下文中將session和request刪除,到此,session的生命周期結束。

視圖函數使用session

在介紹flask的上下文中就已經對session進行過介紹,其本質也是通過LocalProxy操作上下文從而設置session,我們以session['username']='wd'作為列子,首先根據

session = LocalProxy(partial(_lookup_req_object, 'session'))

session是一個LocalProxy對象,執行session['username']=‘wd'則執行LocalProxy對象的__setitem__方法,而__setitem__方法中則是調用_get_current_object獲取ctx中的session對象,而其對象本質是一個特殊的字典,相當于在字典中加一對key,value。

小結

flask內置session本質上依靠上下文,當請求到來時,調用session_interface中的open_session方法解密獲取session的字典,并保存在RequestContext.session中,也就是上下文中,然后在視圖函數執行完畢后調用session_interface的save_session方法,將session以加密的方式寫入response的cookie中,瀏覽器再保存數據。而第三方的session組件原理就是基于是open_session方法和save方法,從而實現session更多的session保存方案。

三、第三方組件flask-session

flask-session支持多種數據庫session保存方案如:redis、memchached、mongodb甚至文件系統等。官方文檔: https://pythonhosted.org/Flask-Session/

安裝:

pip3 install flask-session

redis

import redis
from flask import Flask, session
from flask_session import Session
from datetime import timedelta

app = Flask(__name__)
app.debug = True
app.secret_key = 'adavafa'



app.config['SESSION_TYPE'] = 'redis' # session類型為redis
app.config['SESSION_PERMANENT'] = True # 如果設置為True,則關閉瀏覽器session就失效。
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(seconds=20)
#一個持久化的會話的生存時間,是一個datetime.timedelta對象,也可以用一個整數來表示秒,前提設置了PERMANENT_SESSION_LIFETIME為True
app.config['SESSION_USE_SIGNER'] = False # 是否對發送到瀏覽器上session的cookie值進行加密,默認False 
app.config['SESSION_KEY_PREFIX'] = 'flask-session' # 保存到redis中的key的前綴
app.config['SESSION_COOKIE_NAME']= 'session_id'  # 保存在瀏覽器的cookie名稱
app.config['SESSION_REDIS'] = redis.Redis(host='10.1.210.33', port=‘6379',password=‘123123') # 用于連接redis的配置


#其他配置,不經常使用
app.config['SESSION_COOKIE_DOMAIN']='127.0.0.1' # 設置cookie的域名,不建議設置默認為server_name
app.config['SESSION_COOKIE_PATH']='/' # 會話cookie的路徑。 如果未設置,則cookie將對所有url有效,默認為'/'
app.config['SESSION_COOKIE_HTTPONLY']=True # 是否啟動httponly,默認為true,為了防止xss腳本訪問cookie

Session(app)
@app.route('/login')
def index():
 session["username"]="jack"
 return 'login'


if __name__ == '__main__':
 app.run()

Memchached

import memcache
from flask import Flask, session
from flask_session import Session
from datetime import timedelta

app = Flask(__name__)
app.debug = True
app.secret_key = 'adavafa'



app.config['SESSION_TYPE'] = ‘memcached' # session類型為memcached 
app.config['SESSION_PERMANENT'] = True # 如果設置為True,則關閉瀏覽器session就失效。
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(seconds=20)
#一個持久化的會話的生存時間,是一個datetime.timedelta對象,也可以用一個整數來表示秒,前提設置了PERMANENT_SESSION_LIFETIME為True
app.config['SESSION_USE_SIGNER'] = False # 是否對發送到瀏覽器上session的cookie值進行加密,默認False
app.config['SESSION_KEY_PREFIX'] = 'flask-session' # 保存到緩存中的key的前綴
app.config['SESSION_COOKIE_NAME']= 'session_id'  # 保存在瀏覽器的cookie名稱
app.config['SESSION_MEMCACHED'] = memcache.Client(['10.1.210.33:12000']) #連接


#其他配置,不經常使用
app.config['SESSION_COOKIE_DOMAIN']='127.0.0.1' # 設置cookie的域名,不建議設置默認為server_name
app.config['SESSION_COOKIE_PATH']='/' # 會話cookie的路徑。 如果未設置,則cookie將對所有url有效,默認為'/'
app.config['SESSION_COOKIE_HTTPONLY']=True # 是否啟動httponly,默認為true,為了防止xss腳本訪問cookie




Session(app)


@app.route('/login')
def index():
 session["username"]="jack"
 return 'login'


if __name__ == '__main__':
 app.run()

Filesystem

from flask import Flask, session
from flask_session import Session
from datetime import timedelta

app = Flask(__name__)
app.debug = True
app.secret_key = 'adavafa'



app.config['SESSION_TYPE'] = 'filesystem' # session類型為filesystem
app.config['SESSION_FILE_DIR']='/opt/db' #文件保存目錄
app.config['SESSION_FILE_THRESHOLD'] = 300 # 存儲session的個數如果大于這個值時,開始刪除

app.config['SESSION_PERMANENT'] = True # 如果設置為True,則關閉瀏覽器session就失效。
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(seconds=20)
#一個持久化的會話的生存時間,是一個datetime.timedelta對象,也可以用一個整數來表示秒,前提設置了PERMANENT_SESSION_LIFETIME為True
app.config['SESSION_USE_SIGNER'] = False # 是否對發送到瀏覽器上session的cookie值進行加密,默認False
app.config['SESSION_KEY_PREFIX'] = 'flask-session' # 保存到文件中的key的前綴
app.config['SESSION_COOKIE_NAME']= 'session_id'  # 保存在瀏覽器的cookie名稱


#其他配置,不經常使用
app.config['SESSION_COOKIE_DOMAIN']='127.0.0.1' # 設置cookie的域名,不建議設置默認為server_name
app.config['SESSION_COOKIE_PATH']='/' # 會話cookie的路徑。 如果未設置,則cookie將對所有url有效,默認為'/'
app.config['SESSION_COOKIE_HTTPONLY']=True # 是否啟動httponly,默認為true,為了防止xss腳本訪問cookie

Session(app)


@app.route('/login')
def index():
 session["username"]="jack"
 return 'login'


if __name__ == '__main__':
 app.run()

mongodb

import pymongo
from flask import Flask, session
from flask_session import Session
from datetime import timedelta

app = Flask(__name__)
app.debug = True
app.secret_key = 'adavafa'


app.config['SESSION_TYPE'] = 'mongodb' # session類型為mongodb
app.config['SESSION_MONGODB'] = pymongo.MongoClient('localhost',27017)
app.config['SESSION_MONGODB_DB'] = '數據庫名稱'
app.config['SESSION_MONGODB_COLLECT'] = '表名稱'


app.config['SESSION_PERMANENT'] = True # 如果設置為True,則關閉瀏覽器session就失效。
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(seconds=20)
#一個持久化的會話的生存時間,是一個datetime.timedelta對象,也可以用一個整數來表示秒,前提設置了PERMANENT_SESSION_LIFETIME為True
app.config['SESSION_USE_SIGNER'] = False # 是否對發送到瀏覽器上session的cookie值進行加密,默認False
app.config['SESSION_KEY_PREFIX'] = 'flask-session' # 保存的session的key的前綴
app.config['SESSION_COOKIE_NAME']= 'session_id'  # 保存在瀏覽器的cookie名稱


#其他配置,不經常使用
app.config['SESSION_COOKIE_DOMAIN']='127.0.0.1' # 設置cookie的域名,不建議設置默認為server_name
app.config['SESSION_COOKIE_PATH']='/' # 會話cookie的路徑。 如果未設置,則cookie將對所有url有效,默認為'/'
app.config['SESSION_COOKIE_HTTPONLY']=True # 是否啟動httponly,默認為true,為了防止xss腳本訪問cookie

Session(app)


@app.route('/login')
def index():
 session["username"]="jack"
 return 'login'


if __name__ == '__main__':
 app.run()

sqlalchemy

import redis
from flask import Flask, session
from flask_session import Session 
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.debug = True
app.secret_key = 'adavafa'

# 設置數據庫鏈接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:dev@127.0.0.1:3306/devops?charset=utf8'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# 實例化SQLAlchemy
db = SQLAlchemy(app)
app.config['SESSION_TYPE'] = 'sqlalchemy' # session類型為sqlalchemy
app.config['SESSION_SQLALCHEMY'] = db # SQLAlchemy對象
app.config['SESSION_SQLALCHEMY_TABLE'] = '表名' # session要保存的表名稱

app.config['SESSION_PERMANENT'] = True # 如果設置為True,則關閉瀏覽器session就失效。
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(seconds=20)
#一個持久化的會話的生存時間,是一個datetime.timedelta對象,也可以用一個整數來表示秒,前提設置了PERMANENT_SESSION_LIFETIME為True
app.config['SESSION_USE_SIGNER'] = False # 是否對發送到瀏覽器上session的cookie值進行加密,默認False
app.config['SESSION_KEY_PREFIX'] = 'flask-session' # 保存的session的key的前綴
app.config['SESSION_COOKIE_NAME']= 'session_id'  # 保存在瀏覽器的cookie名稱


#其他配置,不經常使用
app.config['SESSION_COOKIE_DOMAIN']='127.0.0.1' # 設置cookie的域名,不建議設置默認為server_name
app.config['SESSION_COOKIE_PATH']='/' # 會話cookie的路徑。 如果未設置,則cookie將對所有url有效,默認為'/'
app.config['SESSION_COOKIE_HTTPONLY']=True # 是否啟動httponly,默認為true,為了防止xss腳本訪問cookie




Session(app)


@app.route('/login')
def index():
 session["username"]="jack"
 return 'login'


if __name__ == '__main__':
 app.run()


###使用SQLAlchemy時候先確保數據庫和表都存在
在命令行中創建表
#>>> from app import db
#>>> db.create_all()

原理

這里以redis作為session存儲方案做分析,以下是RedisSessionInterface源碼:

class RedisSessionInterface(SessionInterface):
 serializer = pickle
 session_class = RedisSession

 def __init__(self, redis, key_prefix, use_signer=False, permanent=True):
  if redis is None:
   from redis import Redis
   redis = Redis()
  self.redis = redis
  self.key_prefix = key_prefix
  self.use_signer = use_signer
  self.permanent = permanent

 def open_session(self, app, request):
  sid = request.cookies.get(app.session_cookie_name)
  if not sid:
   sid = self._generate_sid()
   return self.session_class(sid=sid, permanent=self.permanent)
  if self.use_signer:
   signer = self._get_signer(app)
   if signer is None:
    return None
   try:
    sid_as_bytes = signer.unsign(sid)
    sid = sid_as_bytes.decode()
   except BadSignature:
    sid = self._generate_sid()
    return self.session_class(sid=sid, permanent=self.permanent)

  if not PY2 and not isinstance(sid, text_type):
   sid = sid.decode('utf-8', 'strict')
  val = self.redis.get(self.key_prefix + sid)
  if val is not None:
   try:
    data = self.serializer.loads(val)
    return self.session_class(data, sid=sid)
   except:
    return self.session_class(sid=sid, permanent=self.permanent)
  return self.session_class(sid=sid, permanent=self.permanent)

 def save_session(self, app, session, response):
  domain = self.get_cookie_domain(app)
  path = self.get_cookie_path(app)
  if not session:
   if session.modified:
    self.redis.delete(self.key_prefix + session.sid)
    response.delete_cookie(app.session_cookie_name,
          domain=domain, path=path)
   return
  httponly = self.get_cookie_httponly(app)
  secure = self.get_cookie_secure(app)
  expires = self.get_expiration_time(app, session)
  val = self.serializer.dumps(dict(session))
  self.redis.setex(name=self.key_prefix + session.sid, value=val,
       time=total_seconds(app.permanent_session_lifetime))
  if self.use_signer:
   session_id = self._get_signer(app).sign(want_bytes(session.sid))
  else:
   session_id = session.sid
  response.set_cookie(app.session_cookie_name, session_id,
       expires=expires, httponly=httponly,
       domain=domain, path=path, secure=secure)

分析:RedisSessionInterface繼承了SessionInterface

class SessionInterface(FlaskSessionInterface):

 def _generate_sid(self):
  return str(uuid4())

 def _get_signer(self, app):
  if not app.secret_key:
   return None
  return Signer(app.secret_key, salt='flask-session',
      key_derivation='hmac')

而SessionInterface又繼承了FlaskSessionInterface,而FlaskSessionInterface又繼承了flask內置的SessionInterface,并且RedisSessionInterface重寫了內置session的open_session和save_session.

首先是RedisSessionInterface實例化用于初始化配置,例如redis的連接、簽名配置、過期配置、前綴配置等。

接下來看兩個核心方法:open_session方法和save_session方法。

open_session:

def open_session(self, app, request):
 sid = request.cookies.get(app.session_cookie_name) #獲取session id
 if not sid: #判斷session id是否為空,為空表示第一次請求
  sid = self._generate_sid() # 返回使用uuid4隨機字符串
  return self.session_class(sid=sid, permanent=self.permanent)
 if self.use_signer:# 判斷簽名配置
  signer = self._get_signer(app)
  if signer is None:
   return None
  try:
   sid_as_bytes = signer.unsign(sid) # 對session id 進行加密簽名
   sid = sid_as_bytes.decode()
  except BadSignature:
   sid = self._generate_sid()
   return self.session_class(sid=sid, permanent=self.permanent)

 if not PY2 and not isinstance(sid, text_type):
  sid = sid.decode('utf-8', 'strict')
 val = self.redis.get(self.key_prefix + sid) # 獲取seession數據
 if val is not None:
  try:
   data = self.serializer.loads(val) # 反序列化數據
   return self.session_class(data, sid=sid) #返回
  except:
   return self.session_class(sid=sid, permanent=self.permanent)
 return self.session_class(sid=sid, permanent=self.permanent)

改方法先從cookie中獲取session id,然后對session id判斷是否為空,為空表示第一次請求,則通過self._generate_sid()返回隨機字符串,作為返回給瀏覽器的sessionid

def _generate_sid(self):
 return str(uuid4())

接著判斷簽名判斷是否為true,然后對session 進行簽名,這里和內置session不同的是獲取session的時候通過self.redis.get(self.key_prefix + sid)在redis中進行獲取。

save_session:

def save_session(self, app, session, response):
 domain = self.get_cookie_domain(app) # 獲取cookie中的域名
 path = self.get_cookie_path(app) # 獲取cookie 中path
 if not session: # 判斷有誤session對象
  if session.modified: #沒有但是被修改了,表示已經被刪除了
   self.redis.delete(self.key_prefix + session.sid) #清空session
   response.delete_cookie(app.session_cookie_name,
         domain=domain, path=path)
  return

 httponly = self.get_cookie_httponly(app)
 secure = self.get_cookie_secure(app)
 expires = self.get_expiration_time(app, session)
 val = self.serializer.dumps(dict(session))
 self.redis.setex(name=self.key_prefix + session.sid, value=val,
      time=total_seconds(app.permanent_session_lifetime)) #保存session
 if self.use_signer:
  session_id = self._get_signer(app).sign(want_bytes(session.sid))
 else:
  session_id = session.sid
 response.set_cookie(app.session_cookie_name, session_id, # 設置cookie
      expires=expires, httponly=httponly,
      domain=domain, path=path, secure=secure)

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

普兰县| 海门市| 建湖县| 贡觉县| 离岛区| 石屏县| 农安县| 东乡| 湖南省| 南安市| 湟中县| 洪泽县| 江油市| 黄大仙区| 揭东县| 香格里拉县| 北安市| 嘉定区| 万安县| 张家界市| 宜宾县| 射洪县| 肇庆市| 广元市| 宜章县| 湖北省| 登封市| 九台市| 澎湖县| 梁平县| 六安市| 临洮县| 商水县| 芷江| 邵阳市| 通化市| 澄城县| 庐江县| 赫章县| 同江市| 临沂市|