iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0
Modern Web

這些那些你可能不知道我不知道的Web技術細節系列 第 18

你可能不知道cookie可以寄城市還可以分路段

  • 分享至 

  • xImage
  •  

預設收件區

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。這是因為localhost326.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 同樣可以看到 nicknamepath0。不過 http://127.0.0.1.nip.io:8000/index6.html 卻看不到。

小結語

因為最近都在寫前後分離的應用,其實對於cookie並不是經常應用。不過cookie對於MVC架構等並非前後分離的Web服務卻很重要。或許在開發時並不需要關注Domain、Path等設定,但是相關的影響對於部署時確是需要考慮的。因為一個沒弄好,不同應用之間就會互相影響,尤其更經常的會使用Nginx等進行反向代理,實際上背後到底有多少不同的應用在提供服務,從表面上很難看出來。微服務設計架構下,應該更尤為明顯。

本文同時發表於我的隨筆


上一篇
你可能不知道cookie是怎麼被製造出來的
下一篇
你可能不知道cookie有些只能走特定道路(HTTP)
系列文
這些那些你可能不知道我不知道的Web技術細節33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言