前端工程師的Authentication(一) — Stateless 、Stateful HTTP

洛
7 min readMar 11, 2022

--

後端工程的系統行為 — Authentication, Authorization, Accounting 被稱為AAA機制,一直是一個很經典去了解後端系統的方法。而其中我覺得對前端工程師最重要的,應該就是 Authenication 的部分,在送出 API Call的時候,應該常常會出現加上這樣的header,

{
Authorization: `Bear token ${userToken}`
}

我們只知道他是用在資安上的,但卻不知道他是怎麼運作的,有點知其然不知其所以然的感覺,對一個工程師來說多少是不好,甚至是危險的。所以,讓我們來更了解這個常見的議題吧!

Stateful and Stateless

我在一開始接觸這個議題的時候,被一大堆的名詞解釋搞的非常的混亂,首先是cookie、session、token是什麼,接下來又出現了token-base 和session-base authentication,還有JWT和session-id又是什麼東東。其實這些名詞都不重要,因為所有的東西我覺得都可以用一個概念概括 -『Stateful』。為了不讓大家搞混,我們一步步慢慢來,先說明什麼是Stateful 和 Stateless 吧。

HTTP is Stateless Protocol

首先,讓我們從最根本得東西,HTTP Request 開始談起吧!HTTP Protocol有一個最重要的特性,那就是他是『Stateless』的,什麼意思呢,簡單說就是今天 Client 像 server 發出一個 request,並附上了帳號和密碼成功獲得了使用者的秘密個資,但如果 Client 還需要發出另一個 request 去取得其他的秘密資訊仍需要附上帳號與密碼在這個新的 request 中,發現了嗎?重點是『Server不會記住現在發 request 的 client 之前做的事』,即使 client 在 10秒前已經做好身份驗證了, server也不管。

取一個現實一點的例子,server像早餐店阿姨,client是你,你先發出了點餐的這個request和說出你的名字 ,阿姨收到了並開始做早餐,當你要去拿早餐的時候,阿姨不是看到你的臉就知道你是10秒前點餐的弟弟,而是要你報上名字,阿姨根據名字去拿做好的早餐給你。而 HTTP 中的『Stateless』就是這樣的性質。

很明顯,這樣的溝通方法並不好,因為每一次 client 都需要附上關於自身身份的驗證訊息,所以,我們是否可以在 request header中夾帶著一些資料,做到 stateful communication的方法呢?

Stateful and Authentication

沒錯,進入我們的重點了,Stateful 的 HTTP 是有可能的,只要我們在 HTTP header 加入一些資料,可以讓每次的 request 都帶有一些『state』,表示這個 client 之前做過的事,可以想成點餐的號碼牌,可以讓你們溝通的更方便,不用每次都需要加上你的使用者密碼跟名稱。而當這些state 是用於身份驗證的時候,就變成了所謂的 『Authentication 』啦!

Terminology — Session and Cookie

說完了概念,讓我們說一些重要的名詞解釋吧 session 和 cookie 在我找個資料中,是最初出現的兩個名詞,為了找出最初的定義,我去看了 RFC 的文章,找出了 cookie 這個名詞最初的背景與用意。

the technique allows clients and servers that wish to exchange state information to place HTTP requests and responses within a larger context, which we term a "session"

上面的的文字來自於 RFC2109 ,session 的定義其實就是我們上面說到的『Stateful 的 HTTP Communication 』,而 cookie 呢,就是 『implement』session ,也 Stateful 的 HTTP Communication 就是的一種方法。

讀到這邊的各位,可能有些疑惑,因為很多時候開發者們喜歡將 session 這個詞都跟『session Id』這個技術畫上等號。但我比較偏好把 session-id 和session 分開來說 ,就是『session-id 是一個 implement session 的方法』。(如果不知道什麼是 session -id 的話,可以先不要管 XD)。

Cookie header and Set-Cookie header

而 cookie 是怎麼運作的呢,其實他用到了兩個特別的header。client 端會使用 Cookie header,而 server 則使用了 Set-Cookie 這個 header。

首先,Cookie 端在發出 request 的時候,會在 header 中加入 Cookie header ,可以在一個 Cookie header 中加上多個 key-value pair 的內容。

再來,server 可以讀取 Cookie header 的方法取的 client 的 key-value pair,這個 key-value pair 就是可以用於 stateful communication 的內容。同樣的,server 也可以由 Set-Cookie 去設定給 Client 的 Cookie 內容

開發上的簡單例子

開發上,前端可以經由 Browser API 去設定 cookie 給 server如下:

document.cookie = `${key}=value`;

而當你前端在發出任何 request 時 (經由 fetch API 或是 XMLHttpRequest ),browser 會自動幫你在 request 的 header 中加上 Cookie 的 header 和相對應的 value。

後端在開發上則可以使用框架,或是直接讀取 headers 中 Cookie header 的值去做 parsing 取得需要的值,以我常用的 express 為例:

上面的內容都是由 Client 發起的 Cookie 流程,但實際上,Cookie 的發起可以由 Client 開始,也可以由 Server 開始, Client 可以在任何時間經由 Browser API 去設定 Cookie , Server 也可以在任何 Response 中加入 Set-Cookie 的 Header 。

這邊說明了什麼是 Stateful 和 StateLess 的 HTTP ,並帶出了兩個基本的名詞概念 Cookie 和 Session ,最後,再簡單的說明一下 Cookie 的使用,接下來的文章,會更深入的介紹 Authentication 這件事。

--

--