




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
請求響應(yīng)循環(huán)其實(shí)大家對于HTTP協(xié)議應(yīng)該是再熟悉不過了,它是超文本傳輸協(xié)議,定義了服務(wù)器和客戶端之間信息交流的格式和傳遞方式。那么對于上面的問題,我們其實(shí)也可以大致的說出一個簡易流程:按下Enter之后,瀏覽器會向URL地址發(fā)送一個HTTP請求在瀏覽器的背后,有一個后臺程序,用于接收相關(guān)請求,并返回處理的結(jié)果瀏覽器接收結(jié)果,并渲染給終端用戶查看事實(shí)上,每一個Web應(yīng)用都包含這種處理模式,即“請求-響應(yīng)循環(huán)(Request-ResponseCycle)”:客戶端(瀏覽器等)發(fā)出請求,服務(wù)端處理請求并響應(yīng)。我們再把上面的流程擴(kuò)展到Flask服務(wù)器上,就是由瀏覽器生成的HTTP請求發(fā)送至Web服務(wù)器。Web服務(wù)器接收到請求后,經(jīng)由WSGI協(xié)議把數(shù)據(jù)轉(zhuǎn)換成Flask程序能夠識別的數(shù)據(jù)后,傳遞給Flask程序。然后Flask程序再根據(jù)視圖函數(shù)等處理相關(guān)請求,最后再返回響應(yīng)給Web服務(wù)器。最終交由瀏覽器來渲染結(jié)果,比如加載CSS,執(zhí)行JavaScript代碼等等操作。我們可以看下下面的圖片這里有兩個概念我們要先明確下Web服務(wù)器:Web服務(wù)器是一類特殊的服務(wù)器,其作用是主要是接收HTTP請求并返回響應(yīng)。我們常用的Web服務(wù)器有Nginx,tomcat等,相信大家都非常熟悉或多少聽說些。WSGI:它確切來說應(yīng)該是一種協(xié)議,或者接口規(guī)范。定義了web服務(wù)器和web應(yīng)用(Flask等)之間的接口規(guī)范。只有Web服務(wù)器和Web應(yīng)用都遵守了WSGI協(xié)議,那么他們才能正常通信。比如說在上一節(jié)我們使用app.run()啟動測試服務(wù)器時,就是使用了Flask自帶的Web服務(wù)器,當(dāng)然這種服務(wù)器只能用來開發(fā)測試時使用,在生成環(huán)境,我們需要部署到Nginx等Web服務(wù)器上。在了解了Web程序的整體運(yùn)行流程之后,我們再來深入的探究下Flask的工作原理。Flask上下文HTTP請求當(dāng)Flask接收到客戶端的請求后(后面的章節(jié)中我們都會直接省略Web服務(wù)器和WSGI的轉(zhuǎn)換步驟),就會產(chǎn)生一些視圖函數(shù)可以訪問的對象,通過這些對象來處理請求,這就是請求對象--request。request對象包含了HTTP請求中的URL信息和相關(guān)的報(bào)文信息URL信息例如請求URL為:xxxx://xxx.xxxxxxxi.xxx/hello?name=xxxxx屬性值path'/hello'full_path'/hello?name=xxxxx'host'xxx.xxxxxxxxi.top'host_url'xxxx://xxx.xxxxxxxx.top'base_url'xxxx://www.xxxxxx.top/hello'url'xxxx://xxx.xxxxxxxi.xxx/hello?name=xxxxx'報(bào)文信息屬性或方法說明args查詢字符串信息cookiescookies信息字典data字符串形式的請求數(shù)據(jù)form表單數(shù)據(jù)get_json()獲取json類型的請求數(shù)據(jù)method請求的HTTP方法下面我們通過一個簡單的例子來具體查看下@app.route('/test/')
def
test_view():
query
=
'Flask'
if
request.args:
query
=
request.args.get('name',
'Flask')
host
=
request.host
path
=
request.full_path
cookie
=
request.cookies
method
=
request.method
return
"""
<h1>
<p>query
string:
%s</p>
<p>host:
%s</p>
<p>path:
%s</p>
<p>cookies:
%s</p>
<p>method:
%s</p>
</h1>
"""
%
(query,
host,
path,
cookie,
method)當(dāng)我們在瀏覽器輸入:xxxx://xxx.0.0.1:5000/test/,可以得到當(dāng)我們在瀏覽器輸入:xxxx://xxx.0.0.1:5000/test/?name=luobo,可以得到在這里,request是一個全局的變量,我們可以在任何的視圖函數(shù)中去使用它。當(dāng)然,這僅僅局限在當(dāng)前線程中,對于多線程服務(wù)器中,不同線程服務(wù)器的請求對象是不同的。兩種上下文在Flask中,有兩種上下文:程序上下文和請求上下文。主要包括下面四種變量名上下文類型說明request請求上下文請求對象,封裝了HTTP請求中的內(nèi)容session請求上下文請求上下文用戶會話,存儲請求之間需要保留的值g程序上下文處理請求時的臨時存儲對象,僅在當(dāng)前請求有效current_app程序上下文當(dāng)前的程序?qū)嵗龑τ趓equest,我們已經(jīng)了解了,下面再來看看session。sessionsession最常用的就是確認(rèn)用戶狀態(tài)了,比如檢查用戶是否登陸等。下面我們就簡單實(shí)現(xiàn)一個基于瀏覽器的用戶認(rèn)證功能,來理解下session的強(qiáng)大功效。普通的認(rèn)證系統(tǒng),用戶在頁面表單中輸入用戶名和密碼后,后臺程序進(jìn)行確認(rèn),如果認(rèn)證通過,則返回響應(yīng),并在瀏覽器的Cookie中設(shè)入標(biāo)記,例如“l(fā)oginID:User1”。但是因?yàn)闉g覽器Cookie是很容易被修改的,所以如果使用名稱存儲這些信息就會非常不安全,此時就需要session登場了。在Flask中session通過密鑰對數(shù)據(jù)進(jìn)行簽名從而加密數(shù)據(jù),所以我們需要先設(shè)置一個密鑰。app.secret_key
=
'Very
Hard
Secret'當(dāng)然,更加安全的做法是把該密鑰寫到部署服務(wù)器的環(huán)境變量中,對于這種寫法,我們在后面部署程序時再詳細(xì)講解。
接下來我們做模擬用戶認(rèn)證的情況,寫兩個視圖函數(shù),分別模擬登陸和登出場景。@app.route('/login/')
def
login():
session['loginID']
=
'admin'
return
redirect(url_for('welcome'))@app.route('/logout/')
def
logout():
if
'loginID'
in
session:
session.pop('loginID')
return
redirect(url_for('welcome'))再修改welcome視圖函數(shù),用于展示是否登陸@app.route('/user/',
defaults={'name':
'陌生人'})
@app.route('/user/<name>')
def
welcome(name):
res
=
'<h1>Hello,
%s!</h1>'
%
name
if
'loginID'
in
session:
res
+=
'Authenticated'
else:
res
+=
'UnAuthenticated'
return
res這里我們使用了redirect函數(shù),是一個重定向方法。只需要傳入目標(biāo)的URL地址,就可以在視圖函數(shù)處理結(jié)束后跳轉(zhuǎn)至目標(biāo)的頁面。當(dāng)我在瀏覽器輸入:xxxx://xxx.0.0.1:5000/login/的時候,就會在瀏覽器中插入一個加密的cookie并跳轉(zhuǎn)至welcome頁面可以看到,插入的cookie是加密的,這樣就加大了攻擊者的攻擊難度,從而在一定程度上保護(hù)了我們系統(tǒng)的安全。g和current_app其實(shí)你應(yīng)該會有個疑惑,我們已經(jīng)有了一個app程序?qū)嵗?,為什么還需要定義一個current_app變量呢?在不同的視圖函數(shù)中,request對象都表示和視圖函數(shù)對應(yīng)的請求,也就是當(dāng)前請求(currentrequest)。而程序會有多個程序?qū)嵗那闆r,為了能獲取對應(yīng)的程序?qū)嵗皇枪潭ǖ哪骋粋€程序?qū)嵗?,我們就需要使用current_app變量。當(dāng)然對于多個程序?qū)嵗那闆r,我們留待后面的章節(jié)詳細(xì)介紹。g存儲在程序上下文中,而程序上下文會隨著每一個請求的進(jìn)入而激活,隨著每一個請求的處理完畢而銷毀,所以每次請求都會重設(shè)這個值。比如說如果對于某個請求,我們幾個視圖函數(shù)都需要用到一個前端傳遞過來的變量,那么就可以把它保存到g變量當(dāng)中
=
request.args.get('name')這樣,其他的視圖函數(shù)就可以在同一個請求中直接使用來訪問,而不用每次都調(diào)用request了。
對于current_app和g的更多使用方式,在后面的學(xué)習(xí)中我們會慢慢接觸的更多。請求鉤子在處理請求之前或之后執(zhí)行的代碼,就稱為請求鉤子。比如在請求之前,我們需要初始化數(shù)據(jù)庫,創(chuàng)建admin用戶等等,就需要在請求之前調(diào)用請求鉤子來做這件事情。在Flask中提供了四種請求鉤子,以裝飾器的形式注冊到函數(shù),使得我們可以方便的應(yīng)用該功能.鉤子名稱作用before_first_request在處理第一個請求之前運(yùn)行before_request在每次請求之前運(yùn)行after_request如果沒有未處理的異常拋出,則在每次請求之后運(yùn)行teardown_request即使有未處理的異常拋出,也在每次請求之后運(yùn)行在請求鉤子函數(shù)和視圖函數(shù)之間共享數(shù)據(jù)一般使用上下文全局變量g,比如上面的例子我們就可以寫成from
flask
import
g
@app.before_request
def
get_name():
=
request.args.get('name')重定向回上一個頁面功能實(shí)現(xiàn)重定向回上一個頁面,這應(yīng)該是一個非常常見的應(yīng)用場景,那么該如何通過Flask來實(shí)現(xiàn)呢。首先我們修改下login視圖函數(shù),在請求參數(shù)中查找next參數(shù),如果存在則重定向到next參數(shù)對應(yīng)的地址,否則重定向到hello視圖函數(shù)對應(yīng)的地址@app.route('/login/')
def
login():
session['loginID']
=
'admin'
return
redirect(request.args.get('next')
or
url_for('hello'))這里所謂的next參數(shù),其實(shí)只是一種約定俗成的命名方式再修改needpage1視圖函數(shù),如果用戶未登陸則展示登陸鏈接,并保存next參數(shù)@app.route('/needlogin1/')
def
needLogin1():
if
'loginID'
in
session:
return
'<h1>Hello,
needLogin1!</h1>'
else:
return
"""
<h1>Login</h1><a
href="%s">Go
To
Login</a>
"""
%
url_for('login',
next=request.url)這樣,當(dāng)用戶處于未登錄狀態(tài)時,就可以點(diǎn)擊GoToLogin鏈接進(jìn)行登陸,登陸成功之后會自動跳轉(zhuǎn)回當(dāng)前頁面了。安全處理現(xiàn)在我們雖然完成了功能,但是卻還遺留了相關(guān)的安全問題。因?yàn)槲覀兊膎ext參數(shù)是以查詢字符串的方式寫在URL里的,所以如果有人攔截了我們的請求,就可以隨便修改next的指向,此時我們就需要驗(yàn)證next變量是否屬于我們的應(yīng)用,否則很容易被指向外部鏈接,從而造成安全隱患。我們先創(chuàng)建一個檢查URL正確性的函數(shù)from
urllib.parse
import
urlparse
def
check_next(target):
ref_url
=
urlparse(request.host_url)
test_url
=
urlparse(target)
return
ref_loc
==
test_loc該函數(shù)接收目標(biāo)地址為參數(shù),并比較本應(yīng)用的host_url和目標(biāo)地址的host_url是否相同
改寫login視圖函數(shù)@app.route('/login/')
def
login():
session['loginID']
=
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 生態(tài)旅游健康與養(yǎng)生項(xiàng)目可行性研究(模板)
- 關(guān)于成立物流公司可行性研究報(bào)告(范文)
- 麗水2024年浙江麗水市新聞傳媒中心招聘事業(yè)單位工作人員筆試歷年參考題庫附帶答案詳解
- 二零二五版舊機(jī)動車買賣居間服務(wù)合同書模板
- 二零二五版門崗聘用合同書
- 二手房買賣合同公證
- 酒店代理合同書范例
- 2025年4月《粉塵涉爆重大事故隱患解讀》應(yīng)急部
- 引領(lǐng)消費(fèi)潮流的新品場景與熱點(diǎn)打造方案
- 東營2024年山東東營河口區(qū)引進(jìn)急需緊缺衛(wèi)生專業(yè)技術(shù)人才4人筆試歷年參考題庫附帶答案詳解
- 顏色標(biāo)準(zhǔn)LAB值對照表
- 金壇區(qū)蘇科版二年級上冊勞動《06樹葉書簽》課件
- 北斗衛(wèi)星導(dǎo)航理論與應(yīng)用課件(完整版)
- 蝦苗購銷合同模板
- 信號基礎(chǔ)信號—聯(lián)鎖系統(tǒng)
- 2020最新八年級下冊《道德與法治》知識點(diǎn)總結(jié)(最全版)
- 數(shù)學(xué)教師實(shí)習(xí)日記16篇
- 財(cái)產(chǎn)保全申請登記表
- 家裝施工驗(yàn)收手冊(共13頁)
- 《責(zé)任勝于能力》PPT課件.ppt
- 先后天八卦與風(fēng)水羅盤131712904
評論
0/150
提交評論