Flask框架——Session與Cookie

在上篇文章中,我們學(xué)習(xí)了Flask框架——模型關(guān)系(多對多關(guān)系),這篇文章我們學(xué)習(xí)Flask框架——Cookie與Session。

在瀏覽網(wǎng)站的過程中,我們經(jīng)常會遇到需要登錄的情況,有些頁面只有登錄之后才可以訪問,登錄之后關(guān)閉瀏覽器,再重新打開該網(wǎng)站時,就自動登錄了,但有時候過段時間又需要重新登錄,這里面涉及了Cookie和Session的相關(guān)知識。

無狀態(tài)HTTP

在了解Cookie和Session之前,我們先了解HTTP的一個特點(diǎn)——無狀態(tài)。

HTTP的無狀態(tài)是指HTTP協(xié)議對事務(wù)處理是沒有記憶能力的,服務(wù)器并不知道客戶端處于什么狀態(tài)??蛻舳讼蚍?wù)器發(fā)送請求后,服務(wù)器解析請求并返回響應(yīng),服務(wù)器負(fù)責(zé)完成這個過程,但服務(wù)器不會記錄前后狀態(tài)的變化,也就是缺少狀態(tài)的記錄。

假如這個請求是需要用戶登錄后才能發(fā)送的,由于服務(wù)器沒有記錄我們登錄的狀態(tài),那么客戶端就必須登錄后再重新發(fā)送請求,就導(dǎo)致需要傳遞一些重復(fù)的請求才能獲取相應(yīng)的響應(yīng),這樣太浪費(fèi)資源了,于是可以識別用戶信息的技術(shù)出現(xiàn)了——Cookie和Session。

  • Cookie:客戶端,有了Cookie,瀏覽器在下次訪問相同網(wǎng)頁時,就會自動附帶上它,并發(fā)送給服務(wù)器,服務(wù)器通過Cookie識別出是哪個用戶在訪問,然后判斷此用戶是否處于登錄狀態(tài),并返回對應(yīng)的響應(yīng)。

  • Session:服務(wù)端,用來保存用戶的Session信息、屬性以及配置信息。

好了,簡單了解了無狀態(tài)HTTP、Cookie及Session的概念后,接下來我們使用Flask框架來實(shí)現(xiàn)網(wǎng)站狀態(tài)的保持。

Cookie

Cookie用來識別用戶身份,在Flask程序中,如何利用Cookie保持用戶狀態(tài)呢。在客戶端第一次請求服務(wù)器時,服務(wù)器會返回一個響應(yīng)頭帶有Set-Cookie字段的響應(yīng)給客戶端,這個字段用來標(biāo)記用戶??蛻舳藶g覽器會把Cookie保存起來,當(dāng)下一次請求相同的網(wǎng)站時,把保存的Cookie放在一起交給服務(wù)器,服務(wù)器通過Cookie來識別用戶,并返回相應(yīng)的響應(yīng)。

在Flask中,Cookie是在響應(yīng)對象中設(shè)置的,所以先要在視圖函數(shù)的返回值中獲取響應(yīng)對象,再使用set-cookie函數(shù)存儲Cookie。

創(chuàng)建一個Flask項(xiàng)目,其app.py代碼如下所示:

from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)

#登錄視圖函數(shù)
@app.route('/login')
def login():
    return render_template('login.html')    #渲染login.html文件

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

這里創(chuàng)建一個簡單的登錄視圖函數(shù),在templates文件夾中創(chuàng)建模板文件login.html,通過render_template()方法渲染login.html,login.html代碼如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄</title>
</head>
<body>
      <form action = "/getcookie" method = "POST">
         <p><h3>請輸入你的用戶名:</h3></p>
         <p><input type = 'text' name = 'username'/></p>
         <p><input type = 'submit' value = 'Login'/></p>
      </form>
</body>
</html>

這個模板文件login很簡單,通過form表單接收用戶輸入的用戶名,當(dāng)點(diǎn)擊Login按鈕時,將用戶名傳遞到getcookie視圖函數(shù)中,在app.py文件中g(shù)etcookie視圖函數(shù)代碼如下所示:

@app.route('/getcookie',methods=['POST','GET'])
def getcookie():
    if request.method=='POST':          #請求類型為POST
        username=request.form['username']   #獲取請求中的username
        response = redirect(url_for('index'))   #重定向到index路由中,并返回響應(yīng)對象
        response.set_cookie('username',str(username),max_age=18000) #設(shè)置cookie值及屬性
        return response

當(dāng)請求類型為POST時,通過request.form()方法將請求中的username獲取并保存在username中,使用redirect重定向到index視圖函數(shù)中,redirect()方法的返回值是個響應(yīng)對象,獲得響應(yīng)對象后,我們通過.set_cookie()方法來設(shè)置cookie。

.set_cookie()方法語法結(jié)構(gòu)如下:

Response.set_cookie(
    key,        #鍵
    value='',    #值
    max_age=None,   #cookie壽命,以秒為單位,None表示http-only
    expires=None,   #失效時間,datetime對象或者時間戳
    path='/',       #cookie的有效路徑
    domain=None,    #cookie有效域
    secure=None,
    httponly=False)

除了通過redirect()方法獲得響應(yīng)對象外,還可以通過以下方式獲?。?/p>

response=render_template()      #模板渲染       
response=Response()             #Response對象
response=make_response()        #自定義response對象
response=jsonify()              #返回包含json格式數(shù)據(jù)響應(yīng)

通過getcookie視圖函數(shù)設(shè)置cookie值后,重定向到index視圖函數(shù)中,在app.py文件中index代碼如下所示:

@app.route('/index')
def index():
    username = request.cookies.get('username',None)     #獲取cookie值
    if username!=None:
        return render_template('logout.html',username=username) #渲染logout.html到網(wǎng)頁中并傳遞username值
    else:
        return render_template('logout.html')

在index視圖函數(shù)中,通過request.cookies.get()方法獲取名為username的cookie值,根據(jù)username值決定是否將username值傳遞到渲染的logout.html網(wǎng)頁中。

在templates文件夾中創(chuàng)建模板文件logout.html,logout.html文件很簡單,代碼如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>現(xiàn)在登錄的用戶為{{ username }}</h3>
<a href="{{ url_for('logout') }}">退出</a>
</body>
</html>

logout.html接收到username值后就會將該值呈現(xiàn)在網(wǎng)頁中,接下來我們打開http://127.0.0.1:5000/login并在文本框中輸入zhangsan,如下圖所示:


點(diǎn)擊登錄直接跳轉(zhuǎn)到http://127.0.0.1:5000/index,如下圖所示:
打開瀏覽器設(shè)置查看Cookie的存儲,

在瀏覽器設(shè)置中,我們可以找到Cookie的存儲情況,在cookie的有效時間內(nèi),每次訪問http://127.0.0.1:5000/index自動登錄。

可以通過set_cookie()方法設(shè)置cookie,也可以通過.delete_cookie()方法刪除cookie,這里我們通過創(chuàng)建logout視圖函數(shù)來實(shí)現(xiàn)對cookie的刪除,在app.py文件中l(wèi)ogout視圖函數(shù)代碼如下所示:

@app.route('/logout')
def logout():
    response = redirect(url_for('index'))   #重定向到index視圖函數(shù)中,獲取響應(yīng)對象
    response.delete_cookie('username')      #刪除名為username的cookie值
    return response

獲取到響應(yīng)對象再通過delete_cookie()方法將cookie值刪除。當(dāng)我們打開http://127.0.0.1:5000/index網(wǎng)頁時,點(diǎn)擊退出,如下圖所示:


這時我們在瀏覽器設(shè)置中查找cookie值,就會發(fā)現(xiàn)剛才上圖的cookie信息已經(jīng)被刪除,所以我們重新打開http://127.0.0.1:5000/index時,沒有用戶信息。

學(xué)習(xí)通過Cookie來保持網(wǎng)頁的狀態(tài)后,接下來我們通過Session來保持網(wǎng)頁的狀態(tài)。

Session

Session,也稱為會話,本義是指有起有終的一系列動作、消息。

在Web中,Session對象用來存儲特定用戶Session所需的屬性及配置信息。這樣當(dāng)用戶在頁面之間跳轉(zhuǎn)時,存儲在Session對象中變量將不會丟失,會在整個用戶中一直存在下去。當(dāng)用戶請求來自程序頁面時,該用戶還沒有Session的話,那么Web服務(wù)器將自動創(chuàng)建一個Session對象,那么當(dāng)Session過期或被放棄后,服務(wù)器將終止該Session。

在Flask框架中,session是當(dāng)做字典來使用的,接下來我們通過代碼來使用session實(shí)現(xiàn)網(wǎng)頁狀態(tài)的保持。

創(chuàng)建Flask項(xiàng)目,其app.py文件代碼如下所示:

from flask import Flask, render_template, request, redirect, url_for, session
app = Flask(__name__)
app.config['SECRET_KEY']='SDFAFASD'         #配置SECRET_KEY
# 登錄視圖函數(shù)
@app.route('/login')
def login():
    return render_template('login.html')    #渲染login.html模板
if __name__ == '__main__':
    app.run()

因?yàn)镕lask的session是通過加密之后放到了cookie中,所以只要用到了Flask的session模塊就一定要配置“SECRET_KEY”這個全局宏。該值可以是任意字符串。

我們創(chuàng)建一個簡單的登錄視圖函數(shù),通過render_template()方法將login.html模板文件渲染在網(wǎng)頁中,這里的login.html我們用上面Cookie的login.html。

接下來我們創(chuàng)建設(shè)置Session的getsession視圖函數(shù),代碼如下所示:

@app.route('/getsession',methods=['POST','GET'])
def getsession():
    if request.method=='POST':
        username=request.form['username']       #獲取請求的username值
        session['username']=username            #設(shè)置session為username
        session.permanent = True               #設(shè)置session有效時長
        return redirect(url_for('index'))       #將網(wǎng)頁重定向到index中

獲取到請求username值,由于session是以字典的形式存在,所以我們需要以session['...‘]=值的形式傳遞,這個我們通過session.permanent=True,將session的有效期延長至一個月,當(dāng)沒有設(shè)置session的有效期時,當(dāng)關(guān)閉瀏覽器時,網(wǎng)頁就是刪除session數(shù)據(jù)信息。除了將session有效期設(shè)置為一個月,還可以通過配置PERMANENT_SESSION_LIFETIME指定session有效時間,代碼如下所示:

app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=2)   #有效時長為2小時

通過getsession視圖函數(shù)設(shè)置session值后,重定向到index視圖函數(shù)中,在app.py文件中index代碼如下所示:

@app.route('/index')
def index():
    username=session.get('username')            #獲取session中的username值
    if username!=None:
        return render_template('logout.html',username=username)     #渲染logou.html并傳遞username值
    else:
        return render_template('logout.html')

和Cookie的index視圖函數(shù)類似,只是將request.cookie改為session,在獲取到username之后,根據(jù)username值判斷是否傳入render_template()渲染的網(wǎng)頁中。這里的logout.html模板是用上面Cookie創(chuàng)建的logout.html模板。

打開http://127.0.0.1:5000/login并在文本框中輸入zhangsan,如下圖所示:


點(diǎn)擊登錄直接跳轉(zhuǎn)到http://127.0.0.1:5000/index,如下圖所示:

在session的有效時間內(nèi),每次訪問http://127.0.0.1:5000/index自動登錄。

如何刪除session數(shù)據(jù)信息呢?刪除session數(shù)據(jù)很簡單,代碼如下所示:

@app.route('/logout')
def logout():
    session.pop('username')                 #刪除session中的username值
    session.clear()                        #刪除session的所有值
    return redirect(url_for('index'))       #重定向到index頁面中

當(dāng)我們打開http://127.0.0.1:5000/index網(wǎng)頁時,點(diǎn)擊退出,如下圖所示:


好了,關(guān)于Flask框架——Session和Cookie就講到這里了,感謝觀看?。?!下篇文章學(xué)習(xí)Flask框架——flask-caching緩存。

公眾號:白巧克力LIN

該公眾號發(fā)布Python、數(shù)據(jù)庫、Linux、Flask、自動化測試、Git等相關(guān)文章!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ? ??在第1章,我們已經(jīng)了解了Flask的基本知識,如果想要進(jìn)一步開發(fā)更復(fù)雜的Flask應(yīng)用,我們就得了解F...
    懵懂_傻孩紙閱讀 3,111評論 0 4
  • 前言 本文為《Flask Web開發(fā):基于Python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)》第2版 的內(nèi)容摘要 摘要 第 1 章:...
    Whyn閱讀 1,232評論 0 0
  • 第二部分 Blog例子 第八章 用戶驗(yàn)證 大部分程序需要追蹤用戶身份。當(dāng)用戶連接到程序,通過一系列步驟使自己的身份...
    易木成華閱讀 1,419評論 0 4
  • URL和視圖 安裝Homebrew 在終端輸入以下代碼,安裝Homebrew: Python安裝 mac環(huán)境下默認(rèn)...
    云中的Jason閱讀 1,380評論 0 4
  • Table of Contents WSGIwsgi服務(wù)器作用wsgirefhttp協(xié)議無狀態(tài),短連接,長連接co...
    四月天_da7e閱讀 557評論 0 0

友情鏈接更多精彩內(nèi)容