2017/07/21

Web 技術中的 Session 是什麼?

轉載原文: Web 技術中的 Session 是什麼?


本文目標

在 Web 的世界裡,Session 已經是被廣泛使用的一種技術,大多數的 Web 開發者,肯定都能運用自如。在現今的各類 Web 應用程式的開發框架和工具中,Session 也已經被包裝成容易使用的模式,所以本文也就不再多討論 Session 怎麼去使用,而是著重在 Session 的原理和實現上。要知道,無論是使用哪一種語言,這 Session 概念上都是通用的,沒有什麼不一樣。


Session 是什麼?

Session 之所以會存在,是因為 HTTP 為 stateless 的設計,Server 和 Client 不會一直保持連線狀態,也不會有雙方狀態的即時更新,所以,Server 並不知道 Client 的狀態(像是是否已經登入)。因此,後來的網站開發者,採用 Session 這樣的設計來解決這問題。有趣的是,Session 機制在最早的 CGI 年代,是完全要程式設計師徒手寫出來的,搞死了很多人,不像現在的網站開發者有現成的許多解決方案可以選擇,不必完全了解也可以使用。


Session 的原理

很多人在討論 Session 時,不免與 Cookie 牽扯上關係,反而不小心偏了重點,所以在了解 Session 時必須有個觀念,就算沒有 Cookie 的存在,Session 機制也可以正常運作。Cookie 在 Session 機制中,可以扮演許多角色,也可以對原始的 Session 機制做許多改良,但不用急著過早討論。從 Session 為什麼被需要來切入,自運作原理來了解,反而比較實際也易懂。最後再來討論 Cookie 在裡面所扮演的角色,才會比較清楚。

簡單來說,Session 的機制就像是你去飲料店下了單以後,得到號碼牌,然後你走開幾步,店員就忘了你是誰。所以,如果你想去取飲料,你就得靠這張號碼牌,去跟店員領,店員會跟據這號碼牌,認定你是顧客、是否點過餐、知道你點了什麼東西,然後可以接著給你屬於你的飲料。

理解 Session 的原理後,回到 HTTP 上就是一樣的。只是,在網頁技術中,有兩種方法讓 Client 取得號碼牌,一個是用 Cookie,另一個是直接輸出並嵌入頁面之中的方法(就是要你把號碼背起來)。

拿號碼牌去 Server 要資料,主要也分為兩種方法,Cookie 和運用標準的 Query string/POST body方法。(其實只要能把號碼傳到 Server 上,任何方法都行)

只不過,因為實作上的困難度考量,還有現今的 Browser 預設都支援 Cookie,所以在現有的網站框架中,都預設採用 Cookie 來發號碼牌和兌換資料。Cookie 的交換會在建立連線時,在背景自動完成,因此開發者不必考慮Client/Server的號碼牌交換問題。因為 Browser 會在建立連線後,第一時間就自動在背景把 Cookie 上傳到 Server,Server 也在回傳資料時,第一時間自動把 Cookie 回傳給 Client。

所以,除非是有必要(像是 Browser/Client 不支援 Cookie 的情況),才會保留另一種實作。

BTW, 飲料店拿號碼牌的例子應該很容易解釋清楚 Session 的原理。


Cookie-based Session

這邊要注意的是,有一種 Session 會讓很多很多人感到混亂,就是 cookie-based session。問題在於名稱上的誤導,你可能會想,既然幾乎所有的 Session 機制都會用到 cookie,是否都可以稱做 cookie-based session?

其實大多數人說的 cookie-based session ,指的是儲存資料方式的不同,不是指領號碼牌時,是否有用到 cookie。(不過如果早個十年,當時講的 cookie-based session,可能多半指的就是領號碼牌時,有沒有用到 cookie。摔碗!)

很多人在討論 Cookie 與 Session 的關係時,兩種用到 Cookie 的地方,時常混在一起講,這就不免要雞同鴨講筆戰一番了。

事實上,在最原始的 Session 設計,大多開發者都將資料存在 Server 上,也就是你點了什麼飲料,都是記錄在 Server 裡,可能是 Database、記憶體或是檔案,可以以任何一種形式儲存。然後,當你去領飲料時,店員會輸入你的號碼,用你的號碼得知你是否點過餐、點了什麼東西。

一般的小網站,這樣的解決方案並沒有什麼問題。但是對今天這種超大流量的網站服務來說,因為他們有無數台對外的 Server,有如無數個服務窗口,讓顧客總是隨機進入其中一個窗口來兌換飲料,所以後端怎麼存放和共享這個 session 資料,又要兼顧效能和方便維護,就變成是很大的問題。

因此 Cookie-based Session 就被提出為一個解決方案,把資料暫存放在 Cookie 中,讓 Client 自己負責保存。簡單來說,就是把你點什麼飲料,通通直接寫在號碼牌上。Server 就可以直接看你的號碼牌上寫了什麼,而不必花大量時間去後面建立大規模的 Server 來處理 Session 。

不過,這邊要特別提到,因為 cookie 有 4K 資料大小的限制,很多網站服務會選擇 cookie-based 和後端儲存並行的方案。

或許有人會問到 Cookie 是否有可能被篡改?這類安全問題,通常會使用加密手段來解決。一般來說,Cookie-based session 的 cookie 會被加密,只有 Server 才知道如何解開,Client 並沒有能力可以存取,只是得到一個看不懂的包裹,所以不會有安全性的問題(當然還是有機會被破)。

由於仍然存在風險,這也是其中一個原因,為什麼有些網站仍然會採用 cookie-based 和後端儲存 Session 並行的解決方案,或是會避免把敏感資料放在 Cookie-based Session 上。


什麼是 Session 傳值?

時常會聽到『使用 Session 傳值』這類說法,其實就是利用 Session 機制儲存資料,讓不同頁面之間可以互相傳遞資料。其原理通常是使用 Query String 或 POST body 等方法,把資料往 Server 傳之後,在 Server 端將 Client 上傳的資料存在 Session 之中。之後的連線或開啟其它頁面時,因為你拿的號碼牌是同一個,所以在不同的頁面之下,仍然可以讀到前一次所儲存在 Session 的狀態。


2017/07/20

2016/11/25

< script ... type="text/x-tmpl" > 是甚麼語法? 作用為何?

最近在學習使用 jQuery plugin "jQuery-file-upload" 的時候,在其所提供的 PHP 範例出現了一段這樣的語法 :
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
  <tr class="template-download fade">
    {% if (file.error) { %}
        <td></td>
        <td class="name"><span>{%=file.name%}</span></td>
        ...
乍看之下感到很納悶,我用的是 PHP 範例,怎麼會出現類似 ASP 的 % 符號? 再仔細一看,<script> 標籤中出現了 type="text/x-tmpl" 沒見過的 MIME type,猜想這應該是沒學過的語法,上網 google 了之後找出了答案,這是使用 javascript 作為 template engine 將資料輸出成為 html 格式的用法。

把 <script> 標籤的 type 設定為 text/x-tmpl 類型,目的是為了防止瀏覽器將 <script>...</script> 中的內容翻譯成 javascript。也就是刻意讓瀏覽器認不出這段 <script> 的用途,因而跳過這部分。

剩下的工作就是讓專門的 javascript 樣板引擎,將這段內容中的資料,套用一般程式的流程控制輸出成 html 格式。

將變數資料輸出成 html 格式是 server-side 樣板語言(PHP,ASP)的主要功能。只不過在這裡使用 javascript 作為 client-side 的 html 樣板語言。

text/x-tmpl 並非公定標準的 MIME type,而是由樣板引擎的作者自行制定的,其中流程控制的部分也用了特殊的標籤,比如 "{% .... %}",目的是為了和 html 標籤作區別以免混淆。

client-side 樣板引擎有來自不同作者的各種版本,此篇的語法是來自 Sebastian Tschan,他最著名的作品是 jQuery-file-upload

-----
參考資料:

Web 技術中的 Session 是什麼?

轉載原文:  Web 技術中的 Session 是什麼? 本文目標 在 Web 的世界裡,Session 已經是被廣泛使用的一種技術,大多數的 Web 開發者,肯定都能運用自如。在現今的各類 Web 應用程式的開發框架和工具中,Session 也已經被包裝成容易使用的模...