每一次訪問都會在瀏覽器生成Cookie
,那麼Cookie
的存在對於用戶來說是好還是壞呢?說實話,這玩意的存在確實會帶來一系列的問題,有趣的是幾乎每個站點都難以離開Cookie
,由於Cookie
的使用因其貌似簡單,而很容易被人輕視。最近在開發過程中,審視應用中的Cookie
代碼,幾乎只需要很小的代價就可以獲得巨大的安全收益。因此寫下這份筆記加深記憶。
cookie的安全隱患
在實際的應用場景中,Cookie
被用來做得最多的一件事是保持身份認證的服務端狀態。這種保持可能是基於會話Session
的,也有可能是持久性的。然而不管哪一種,身份認證Cookie
中包含的服務端票據Ticket
一旦洩露,那麼服務端將很難區分帶有此票據的用戶請求是來自於真實的用戶,或者是來自惡意的***者。
在實際案例中,造成Cookie
洩露最多的途徑,是通過跨站腳本(如 XSS, Cross Site Script)漏洞。者可以通過一小段JavaScript
代碼,偷竊到代表用戶身份的重要的Cookie
標識。由於跨站腳本漏洞是如此的普遍(不要以為簡單的HTML Encode
就可以避免被跨站,跨站是一門很深的學問,以至於在業界衍生出一個專用的名詞:跨站師),幾乎每一個網站都無法避免,所以這種方式是實際中被普遍使用的一種手段。
事實上避免出現這種問題的首要祕訣就是盡所有的可能,給你的Cookie
加上HttpOnly
的標籤。HttpOnly
的具體使用不在本文的討論範圍內。
Cookie 的工作原理
第一次訪問網站的時候,瀏覽器發出請求,服務器響應請求後,會將Cookie
放入到響應請求中,在瀏覽器第二次發請求的時候,會把Cookie
帶過去,服務端會辨別用戶身份,當然服務器也可以修改Cookie
內容.
Cookie 的生命週期
創建Cookie
的時候,會給Cookie
指定一個值:Expire
,它就是指定Cookie
的有效期,也就是Cookie
的生命週期,超出設置的這個生命週期,Cookie
就會被清除。如果給這個值Expire
設置為0
或者負值,那麼這樣的設置就是在關閉瀏覽器時,就會清除Cookie
,這種方式更加安全。
修改cookie有效期
通常情況下,我們的web
應用服務都會通過nginx
進行發佈,這個時候,我們可以通過在nginx
上面進行配置文件的修改來改變cookie
的有效期,由於筆者最近在基於openresty
對nginx
進行功能開發。正好趁此機會展開對Cookie
有效期的狀態測試.
上文在Cookie
的生命週期中提到為了有效期的安全性,我們可以為Cookie
設置合理的有效期。如為0
或者負值,那麼其效果是怎樣的呢?不妨看一下
修改思路
利用Openresty
的resty.cookie
進行修改。該庫是用來對OpenResty
的HTTP cookie
操作。可以用來為Nginx
解析HTTP Cookie header
,並返回Cookie
中的每個字段。比如設置name
,value
,httponly
等屬性
有效期為24h
這裡將expires
設置為有效期是一天(24h)
即當前系統時間(ngx.time())
加24h
local cookie = resty_cookie:new() local ok, err = cookie:set({ key = "middle_session", value = session, path = "/", secure = false, httponly = true, expires = ngx.cookie_time(ngx.time() + 60 * 60 * 24), domain = ngx.host, })
效果
在這裡可以看到我們cookie
的有效時間為5月13號的14點04分,說明我們的修改配置是有效的,可以通過該參數進行Cookie
修改,只要到達這個時間點,該Cookie
便會失效,此時用戶需要重新登錄。
有效期為創世紀
這裡將expires
設置為有效期是-1,這裡可以觀察到cookie使用的時間的是1970年,也就是UNIX紀元的元時間
local cookie = resty_cookie:new() local ok, err = cookie:set({ key = "middle_session", value = session, path = "/", secure = false, httponly = true, expires = ngx.cookie_time(-1), domain = ngx.host, })
從下圖中可以看到Cookie
有效期是1970年1月1號,這個時間點毫無懸念的已經過時了,當然了,在生產環境中這麼配置。是要被關進小黑屋探討人生價值的,用戶遇到這樣的Cookie
配置是無論如何都無法登陸成功的
有效期為當前
因為ngx.cookie_time
會返回一個格式化的字符串,可以用作Cookie
過期時間,我們自己手動指定過期時間。通過這個方法可以測試上文說到的Cookie
自動清除的效果
指定過期時間為-1
local cookie = resty_cookie:new() local ok, err = cookie:set({ key = "middle_session", value = session, path = "/", secure = false, httponly = true, expires = -1, domain = ngx.host, })
指定過期時間為0
local cookie = resty_cookie:new() local ok, err = cookie:set({ key = "middle_session", value = session, path = "/", secure = false, httponly = true, expires = 0, domain = ngx.host, })
結論
這裡配置-1
,0
在現實意義上跟配置元時間是一樣的,不過好處在於,不用關小黑屋啦。Cookie
只在當前頁面上有效,一旦關閉瀏覽器,這個Cookie
就會被瀏覽器清除,此時不用再考慮安全性問題。
參考文檔:
Cookie 安全漫談 https://www.infoq.cn/article/cookie-security
把cookie聊清楚 https://juejin.im/post/59d1f59bf265da06700b0934
淺談cookie安全 https://zhuanlan.zhihu.com/p/58666986
[wooen ] nginx cookie有效期討論小結已經有476次圍觀