Set-Cookie
就像寫信,除了內容當然還有收件區號。如果並沒有給Domain,就是當前的Domain。比如當瀏覽 http://localhost:8000/index1.html ,其記錄的Domain就是localhost
。
這個Domain就像是在寫信時填寫的區號,比如「桃園市楊梅區」的區號就是326
。
現在可以複製你可能不知道cookie是怎麼被製造出來的裡的DEMO程式碼內容,在此基礎上繼續修改,填寫收件區碼。
@app.get('/index4.html')
def index4():
response = FileResponse('index.html')
max_age = 86400 # 1 day * 24 hour * 60 min * 60 sec
response.set_cookie('sendto326', 'xyz', max_age=max_age, domain='326.127.0.0.1.nip.io')
return response
其實這也就只是在Header的Set-Cookie
添加Domain=<domain>
的資訊而已。瀏覽 http://localhost:8000/index4.html 。
不過或許你也已經發現了,這一次添加並沒有沒有在畫面上顯式sendto326
。這是因為localhost
和326.127.0.0.1.nip.io
並不匹配,因此被(瀏覽器)退信了。這次可以換瀏覽 http://326.127.0.0.1.nip.io:8000/index4.html 看看,就會發現存在這筆訊息。
如果有明確寫區號,子區域同樣可以收到。也就是假設我要寄信到「桃園市楊梅區高獅路601號以上」的地址,區號應該是填寫326024
,但是填寫326
同樣可以收到信。所以現在瀏覽 http://024.326.127.0.0.1.nip.io:8000/index0.html 同樣有該筆記錄。 或是瀏覽 http://024.326.127.0.0.1.nip.io:8000/index4.html 同樣可以收到並將信件拆開閱讀。
如果沒有指定的話,子區域可是收不到的喔~
在添加以下程式片段後,可以瀏覽 http://127.0.0.1.nip.io:8000/index5.html 。
@app.get('/index5.html')
def index5():
response = FileResponse('index.html')
max_age = 86400 # 1 day * 24 hour * 60 min * 60 sec
response.set_cookie('sendto326-1', 'xyz', max_age=max_age, domain='127.0.0.1.nip.io')
response.set_cookie('sendto326-2', 'xyz', max_age=max_age, domain='.127.0.0.1.nip.io')
response.set_cookie('only', 'xyz', max_age=max_age)
return response
可以發現如果指定Domain的話,前面會被添加一個點,表示子網域也可以收到。但是預設卻不會有,也就是當在次瀏覽 http://326.127.0.0.1.nip.io:8000/index0.html ,並不會收到包含only
的訊息。
要注意的是Domain是不分樓層(port)的 。也就是說可不管是寄到2樓還是3樓,只要Domain是對的,就可以收到信。現在可以在多開一個伺服器看看:
uvicorn app:app --port 8001
然後瀏覽 http://326.127.0.0.1.nip.io:8001/index0.html 。會發現同樣可以打開之前閱讀收到的訊息。
傳統登入狀態會話(session)依靠著cookie。
曾經因為在玩一些開源軟體,發現同時起兩個會互相影響,才注意到Domain並沒有判斷Port。
我想這可能是比較少人知道的。
去年鐵人賽參賽主題「用Keycloak學習身份驗證與授權」中介紹的Keycloak,在這一年還有持續再了解相關的使用方式。
其中有一個是 Realm 的設計。不同的 Realm 有著不同的 SSO Session (也就是登入狀態)。這究竟是如何實現的?好奇之下才發現Cookie還有Path可以指定。
除了區號(Domain),還可以指定路段(Path)。再繼續添加程式碼:
@app.get('/index6.html')
def index6():
response = FileResponse('index.html')
max_age = 86400 # 1 day * 24 hour * 60 min * 60 sec
response.set_cookie('nickname', 'LAG', max_age=max_age, path="/path")
return response
@app.get('/path')
def path():
response = FileResponse('index.html')
max_age = 86400 # 1 day * 24 hour * 60 min * 60 sec
response.set_cookie('path0', '%E6%B0%91%E7%94%9F%E8%B7%AF', max_age=max_age, path="/path")
return response
@app.get('/path/sub')
def subPath():
return FileResponse('index.html')
瀏覽 http://127.0.0.1.nip.io:8000/index6.html
會發現雖然收到了nickname
,卻沒顯式在畫面上。這是因為路段(Path)不匹配。不過只要瀏覽 http://127.0.0.1.nip.io:8000/path 就可以正確打開信件讀取內容。不止如此還多添加了這個連接收到的訊息path0
。
子路徑的位置都可以讀取訊息,所以瀏覽 http://127.0.0.1.nip.io:8000/path/sub 同樣可以看到 nickname
、path0
。不過 http://127.0.0.1.nip.io:8000/index6.html 卻看不到。
因為最近都在寫前後分離的應用,其實對於cookie並不是經常應用。不過cookie對於MVC架構等並非前後分離的Web服務卻很重要。或許在開發時並不需要關注Domain、Path等設定,但是相關的影響對於部署時確是需要考慮的。因為一個沒弄好,不同應用之間就會互相影響,尤其更經常的會使用Nginx等進行反向代理,實際上背後到底有多少不同的應用在提供服務,從表面上很難看出來。微服務設計架構下,應該更尤為明顯。
本文同時發表於我的隨筆