1、Cookie、Session和Token的區別
Cookie是瀏覽器用來保存用戶信息的文件,可以保存比如用戶是誰,購物車有哪些商品等。
Session是一次會話,會話是指我們訪問網站的一個周期。
-
比如用戶打開一個瀏覽器訪問某個位的站點。
-
在這個站點點擊多個超鏈接查看各個網頁,然后關閉瀏覽器,整個過程稱之為一個會話。
token是服務器返回的一個臨時簽名數據, 可以使用這個簽名數據表面用戶身份.
為什么會有這三個東西呢? 都是一個目的, 服務器需要知道和自己通話的人是誰, 專業一點就是 服務器需要用某種機制來識別具體的用戶.
這要從HTTP協議開始說起, HTTP協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的連接就會關閉,再次交換數據需要建立新的連接。這就意味着服務器無法從連接上跟蹤會話, 自然無法識別用戶, 所以誕生了Cookie,session和token。
2、什么是Cookie?
Cookie 技術產生源於 HTTP 協議在互聯網上的急速發展。隨着互聯網時代的策馬奔騰,帶寬等限制不存在了,人們需要更復雜的互聯網交互活動,就必須同服務器保持活動狀態(簡稱:保活)。於是,在瀏覽器發展初期,為了適應用戶的需求技術上推出了各種保持 Web 瀏覽狀態的手段,其中就包括了 Cookie 技術。Cookie 在計算機中是個存儲在瀏覽器目錄中的文本文件,當瀏覽器運行時,存儲在 RAM 中發揮作用 (此種 Cookies 稱作 Session Cookies),一旦用戶從該網站或服務器退出,Cookie 可存儲在用戶本地的硬盤上 (此種 Cookies 稱作 Persistent Cookies)。
Cookie使用限制:Cookie 必須在 HTML 文件的內容輸出之前設置;不同的瀏覽器 (Netscape Navigator、Internet Explorer) 對 Cookie 的處理不一致,使用時一定要考慮;客戶端用戶如果設置禁止 Cookie,則 Cookie 不能建立。 並且在客戶端,一個瀏覽器能創建的 Cookie 數量最多為 300 個,並且每個不能超過 4KB,每個 Web 站點能設置的 Cookie 總數不能超過 20 個。
執行流程:
A:首先,客戶端會發送一個http請求到服務器端;
B: 服務器端接受客戶端請求后,發送一個http響應到客戶端,這個響應頭,其中就包含Set-Cookie頭部;意思就是瀏覽器建立一個cookie保存服務器指定的內容,比如用戶信息和用戶操作信息;
C:在客戶端發起的第二次請求(注意:如果服務器需要我們帶上Cookie,我們就需要在B步驟上面拿到這個Cookie然后作為請求頭一起發起第二次請求),提供給了服務器端會從收到的cookie中識別用戶身份,就能讓頁面為你提供專門屬於你的內容了。
D:服務器端可以用來唯一標識客戶端身份的信息。
cookie 可以讓服務端跟蹤每個客戶端的訪問,但是每次客戶端的訪問都必須傳回這些 Cookie,如果 Cookie 很多,這無形地增加了客戶端與服務端的數據傳輸量,
為了方便理解,可以先看下這張流程執行圖加深概念:
cookie具有以下特點
- cookie存儲的數量和字符數量都有限制,只能存儲幾十個,不超4096左右個字符。
- Cookie具有不可跨域名性
很多網站都會使用Cookie。例如,Google會向客戶端頒發Cookie,Baidu也會向客戶端頒發Cookie。那瀏覽器訪問Google會不會也攜帶上Baidu頒發的Cookie呢?或者Google能不能修改Baidu頒發的Cookie呢?
答案是否定的。Cookie具有不可跨域名性。根據Cookie規范,瀏覽器訪問Google只會攜帶Google的Cookie,而不會攜帶Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。
Cookie在客戶端是由瀏覽器來管理的。瀏覽器能夠保證Google只會操作Google的Cookie而不會操作Baidu的Cookie,從而保證用戶的隱私安全。瀏覽器判斷一個網站是否能操作另一個網站Cookie的依據是域名。Google與Baidu的域名不一樣,因此Google不能操作Baidu的Cookie。
需要注意的是,雖然網站images.google.com與網站www.google.com同屬於Google,但是域名不一樣,二者同樣不能互相操作彼此的Cookie。
————————————————
版權聲明:本文為CSDN博主「想名真難」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u014600626/article/details/107807029
- cookie雖然不可跨域名, 但是存儲在用戶瀏覽器里也是不安全的,任何人都能直接查看。
我們以谷歌瀏覽器為例查看cookie,我們右擊找到檢查,點擊打開瀏覽器控制台,或者按F12
找到Console,在其中輸入document.cookie即可查看
3、關於Session
Cookie 雖然很方便,但是使用 Cookie 有一個很大的弊端,
1、Cookie 中的所有數據在客戶端就可以被修改,數據非常容易被偽造,那么一些重要的數據就不能存放在 Cookie 中了,
2、而且如果 Cookie 中數據字段太多會影響傳輸效率。
為了解決前面cookie所提到的這些問題,就產生了 Session,Session 中的數據是保留在服務器端的。
總之:Session是對於服務端來說的,客戶端是沒有Session一說的。Session是服務器在和客戶端建立連接時添加客戶端連接標志,最終會在服務器軟件(Apache、Tomcat、JBoss)轉化為一個臨時Cookie發送給給客戶端,當客戶端第一請求時服務器會檢查是否攜帶了這個Session(臨時Cookie),如果沒有則會添加Session,如果有就拿出這個Session來做相關操作。
Session 的運作通過一個session_id來進行。session_id通常是存放在客戶端的 Cookie 中,比如在 express 中(說的是Nodejs),默認是connect.sid這個字段,當請求到來時,服務端檢查 Cookie 中保存的 session_id 並通過這個 session_id 與服務器端的 Session data 關聯起來,進行數據的保存和修改。
這意思就是說,當你瀏覽一個網頁時,服務端隨機產生一個 1024 比特長的字符串,然后存在你 Cookie 中的connect.sid字段中。當你下次訪問時,Cookie 會帶有這個字符串,然后瀏覽器就知道你是上次訪問過的某某某,然后從服務器的存儲中取出上次記錄在你身上的數據。由於字符串是隨機產生的,而且位數足夠多,所以也不擔心有人能夠偽造。偽造成功的概率比坐在家里編程時被鄰居家的狗突然闖入並咬死的幾率還低。
session在計算機網絡應用中被稱為“會話控制”。不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務器上。在服務端保存Session的方法很多,內存、數據庫、文件都有。
-
客戶端瀏覽器訪問網站的時候,
-
服務器會向客戶瀏覽器發送一個每個用戶特有的會話編號sessionID,讓瀏覽器寫入到cookie里(大多數情況)。服務器同時也把sessionID和對應的用戶信息、用戶操作記錄在服務器上,這些記錄就是session。
-
客戶端瀏覽器再次訪問時,會發送cookie給服務器,cookie中就包含sessionID。
-
服務器從cookie里找到sessionID,再根據sessionID找到以前記錄的用戶信息就可以知道他是誰, 之前操控哪些、訪問過哪里。
從流程上看cookie和session看起來就是一套東西啊, 其實是不一樣的, cookie是文件, 可以存任意東西, sessionID只不過是存的一種數據, 而session數據保存在服務器, 只不過session常見實現方式是借助cookie, 但是可以不用cookie, 使用URL地址重寫來實現session。
使用url重寫實現Session跟蹤
這是在瀏覽器不支持Cookie的情況下,servlet引入的一種補充的會話機制。當用戶發出下一次請求時,如果請求消息中沒有包含Cookie頭字 段,Servlet引擎則認為客戶端不支持Cookie,他將依據請求url參數中的會話標識號來實施會話跟蹤。這種方式要求響應消息中出現的超鏈接地址 后面附帶會話標識號參數,用戶也必須通過超鏈接來提交后續的訪問請求。
這種技術成為url重寫,tomcat發送給客戶端的會話標識號的Cookie名稱為JSESSIONID。url重寫就是將JSESSIONID關鍵字 作為參數名和將會話標識號作為參數附加到URL后面。如果瀏覽器不支持Cookie或者關閉Cookie,就必須對所有可能被客戶端訪問的請求路徑進行 URL重寫,如超鏈接,form表單的action屬性和重定向的URLHttpServletResponse接口定義了兩個用於URL重寫的方法:
encodeURL方法,用於超鏈接和form表單的action屬性中設置的URL進行重寫
encodeRedirectURL 方法 用於對傳遞給HttpServletResponse.sendRedirect方法的URL進行重寫
他們根據請求消息中是否含有Cookie頭字段來決定是否進行url重寫。把URL作為參數傳遞給這兩個方法,他們就能完成url重寫,在url后面添加 jsessionid參數及其值。可以關閉瀏覽器的Cookie,然后,進行實驗,在網頁源文件中查看URL后面是否有jsessionid參數及其值。Session的持久化
客戶端訪問了某個能開啟會話功能的資源, web服務器就會創建一個與該客戶端對應的HttpSession對象,每個HttpSession對象都要站用一定的內存空間。如果在某一時間段內訪問 站點的用戶很多,web服務器內存中就會積累大量的HttpSession對象,消耗大量的服務器內存,即使用戶已經離開或者關閉了瀏覽器,web服務器 仍要保留與之對應的HttpSession對象,在他們超時之前,一直占用web服務器內存資源。
web服務器通常將那些暫時不活動但為超時的HttpSession對象轉移到文件系統或數據庫中保存,服務器要使用他們時再將他們從文件系統或數據庫中裝載入內存,這種技術稱為Session的持久化。
將 HttpSession對象保存到文件系統或數據庫中,需要采用序列化的方式將HttpSession對象中的每個屬性對象保存到文件系統或數據庫中;將 HttpSession對象從文件系統或數據庫中裝載如內存時,需要采用反序列化的方式,恢復HttpSession對象中的每個屬性對象。所以存儲在 HttpSession對象中的每個屬性對象必須實現Serializable接口。Session的持久化的作用:
1.提高服務器內存的利用率,保證那些暫停活動的客戶端在會話超時之前繼續原來的會話
2,在多台web服務器協同對外提供服務的集群系統中,使用Session的持久化技術,某台服務器可以將其中發生改變的Session對象復制給其他服務器。保證了在某台服務器停止工作后可以由其他服務器來接替它與客戶端的會話
3,在一個web應用程序重啟時,服務器也會持久化該應用程序中所有HttpSession對象,保證客戶端的會話活動仍可以繼續。
Tomcat使用Session Manager 類來管理Session的持久化,他提供了兩個SessionManager類
org.apache.catalina.session.StandardManager
org.apache.catalina.session.PersistentManager
StandardManager是tomcat默認使用的,在web應用程序關閉時,對內存中的所有HttpSession對象進行持久化,把他們保存到文件系統中。默認的存儲文件為
<tomcat 安裝目錄>/work/Catalina/<主機名>/<應用程序名>/sessions.ser
PersistentManager比StandardManager更為靈活,只要某個設備提供了實現org.apache.catalina.Store接口的驅動類,PersistentManager就可以將HttpSession對象保存到該設備
————————————————
版權聲明:本文為CSDN博主「mmllkkjj」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/mmllkkjj/article/details/6132139
一個完整的Cookie+Session應用過程如下圖所示:
Session 可以存放在:
1)內存;
2)Cookie本身;
3)redis 或 memcached 等緩存中;
4)數據庫中。
線上來說,緩存的方案比較常見,存數據庫的話,查詢效率相比前三者都太低,不推薦;
隨着Web,應用程序,以及移動端的興起,session驗證的方式逐漸暴露出了問題。尤其是在可擴展性方面。
基於服務器驗證方式暴露的一些問題:
- Seesion:每次認證用戶發起請求時,服務器需要去創建一個記錄來存儲信息。當越來越多的用戶發請求時,服務器端內存的開銷也會不斷增加。
- 可擴展性:在服務端使用Seesion存儲登錄信息,伴隨而來的是可擴展性問題, 多個服務器之間如何同步sessionID。
- CORS(跨域資源共享):當我們需要讓數據跨多台移動設備上使用時,跨域資源的共享會是一個讓人頭疼的問題。在使用Ajax抓取另一個域的資源,就可以會出現禁止請求的情況。
- CSRF(跨站請求偽造):用戶在訪問銀行網站時,他們很容易受到跨站請求偽造的攻擊,並且能夠被利用其訪問其他的網站。
在這些問題中,可擴展性是最突出的:
比如說服務端用兩個機器組成了一個集群, 小F通過機器A登錄了系統, 那sessionID會保存在機器A上, 假設小F的下一次請求被轉發到機器B怎么辦? 機器B可沒有小F的 sessionID啊。
有時候會采用一點小伎倆: session sticky , 就是讓小F的請求一直粘連在機器A上, 但是這也不管用, 要是機器A掛掉了, 還得轉到機器B去。
那只好做session 的復制了, 把sessionID在兩個機器之間搬來搬去, 快累死了。
后來有個叫Memcached的支了招: 把session id 集中存儲到一個地方, 所有的機器都來訪問這個地方的數據, 這樣一來,就不用復制了, 但是增加了單點失敗的可能性, 要是那個負責session 的機器掛了, 所有人都得重新登錄一遍, 估計得被人罵死。
5、什么是Token?
5.1 Token的起源
於是嘗試把這個單點負責session存儲的機器也搞出集群,增加可靠性, 但不管如何, 這小小的session 對服務端來說是一個沉重的負擔.
因此有必要去尋求一種更有行之有效的方法。於是有人就一直在思考, 服務端為什么要保存這可惡的sessionID呢, 只讓每個客戶端去保存該多好?
可是如果不保存這些sessionID , 怎么驗證客戶端發給我的sessionID 的確是服務端生成的呢? 如果不去驗證,我們都不知道他們是不是合法登錄的用戶, 那些不懷好意的家伙們就可以偽造sessionID , 為所欲為了。
嗯,對了,關鍵點就是驗證 !
比如說, 小F已經登錄了系統, 服務端給他發一個令牌(token), 然后把小F的 user_id和token在數據庫(確切說是Redis+數據庫)里做關聯, 下一次小F 再次通過Http 請求訪問我的時候, 把這個token 通過Http header 帶過來不就可以了。
當然, 如果一個人的token 被別人偷走了, 那服務器也沒辦法, 服務器也會認為小偷就是合法用戶, 這其實和一個人的sessionID 被別人偷走是一樣的。
這樣一來, 服務器就不保存sessionID 了,只是生成token , 然后驗證token , 用CPU計算時間獲取了我的session 存儲空間 !
解除了sessionID這個負擔, 可以說是無事一身輕, 我的機器集群現在可以輕松地做水平擴展, 用戶訪問量增大, 直接加機器就行。 這種無狀態的感覺實在是太好了!
在Web領域基於Token的身份驗證隨處可見。在大多數使用Web API的互聯網公司中,token是多用戶下處理認證的最佳方式。
那些使用基於Token的身份驗證的大佬們, 大部分你見到過的API和Web應用都使用tokens。例如Facebook, Twitter, Google+, GitHub等。
基於Token的身份驗證的過程如下:
- 用戶通過用戶名和密碼發送請求。
- 服務端驗證, 返回生成的token 給客戶端, 同時給數據庫和Redis里關聯token和用戶信息。
- 客戶端儲存token,並且其后的每一次請求都添加token, token應該在HTTP的頭部發送從而保證了Http請求無狀態。
- 服務端查詢Redis+數據庫, 驗證token並返回數據。
Token的身份認證邏輯:
對比一:如果兩個 token 值相同, 說明用戶登錄成功過!當前用戶處於登錄狀態!
對比二:如果沒有這個 token 值, 則說明沒有登錄成功;
對比三:如果 token 值不同: 說明原來的登錄信息已經失效,讓用戶重新登錄。
5.3 Tokens的優勢
無狀態
在客戶端存儲的Tokens是無狀態的,並且能夠被擴展。基於這種無狀態和不存儲Session信息,負載負載均衡器能夠將用戶信息從一個服務傳到其他服務器上。
安全性
請求中發送token而不再是發送cookie能夠防止CSRF(跨站請求偽造)。即使在客戶端使用cookie存儲token,cookie也僅僅是一個存儲機制而不是用於認證。不將信息存儲在Session中,讓我們少了對session操作。
token是有時效的,一段時間之后用戶需要重新驗證。我們也不一定需要等到token自動失效,token有撤回的操作,通過token revocataion可以使一個特定的token或是一組有相同認證的token無效。
CSRF的防御
1、盡量使用POST,限制GET
GET接口太容易被拿來做CSRF攻擊,看上面示例就知道,只要構造一個img標簽,而img標簽又是不能過濾的數據。接口最好限制為POST使用,GET則無效,降低攻擊風險。
當然POST並不是萬無一失,攻擊者只要構造一個form就可以,但需要在第三方頁面做,這樣就增加暴露的可能性。
2、將cookie設置為HttpOnly
CRSF攻擊很大程度上是利用了瀏覽器的cookie,為了防止站內的XSS漏洞盜取cookie,需要在cookie中設置“HttpOnly”屬性,這樣通過程序(如JavaScript腳本、Applet等)就無法讀取到cookie信息,避免了攻擊者偽造cookie的情況出現。
在Java的Servlet的API中設置cookie為HttpOnly的代碼如下:
response.setHeader( “Set-Cookie”, “cookiename=cookievalue;HttpOnly”);
3、增加token
CSRF攻擊之所以能夠成功,是因為攻擊者可以偽造用戶的請求,該請求中所有的用戶驗證信息都存在於cookie中,因此攻擊者可以在不知道用戶驗證信息的情況下直接利用用戶的cookie來通過安全驗證。由此可知,抵御CSRF攻擊的關鍵在於:在請求中放入攻擊者所不能偽造的信息,並且該信總不存在於cookie之中。鑒於此,系統開發人員可以在HTTP請求中以參數的形式加入一個隨機產生的token,並在服務端進行token校驗,如果請求中沒有token或者token內容不正確,則認為是CSRF攻擊而拒絕該請求。
假設請求通過POST方式提交,則可以在相應的表單中增加一個隱藏域:token的值通過服務端生成,表單提交后token的值通過POST請求與參數一同帶到服務端,每次會話可以使用相同的token,會話過期,則token失效,攻擊者因無法獲取到token,也就無法偽造請求。
在session中添加token的實現代碼:HttpSession session = request.getSession();
Object token = session.getAttribute("_token");
if(token == null I I "".equals(token)) {
session.setAttribute("_token", UUID.randomUUIDO .toString());
}
4、通過Referer識別
根據HTTP協議,在HTTP頭中有一個字段叫Referer,它記錄了該HTTP請求的來源地址。在通常情況下,訪問一個安全受限的頁面的請求都來自於同一個網站。比如某銀行的轉賬是通過用戶訪問http://www.xxx.com/transfer.do頁面完成的,用戶必須先登錄www.xxx.com,然后通過單擊頁面上的提交按鈕來觸發轉賬事件。當用戶提交請求時,該轉賬請求的Referer值就會是
提交按鈕所在頁面的URL(本例為www.xxx. com/transfer.do)。如果攻擊者要對銀行網站實施CSRF攻擊,他只能在其他網站構造請求,當用戶通過其他網站發送請求到銀行時,該請求的Referer的值是其他網站的地址,而不是銀行轉賬頁面的地址。因此,要防御CSRF攻擊,銀行網站只需要對於每一個轉賬請求驗證其Referer值即可,如果是以www.xx.om域名開頭的地址,則說明該請求是來自銀行網站自己的請求,是合法的;如果Referer是其他網站,就有可能是CSRF攻擊,則拒絕該請求。
取得HTTP請求Referer:
String referer = request.getHeader(“Referer”);
————————————————
版權聲明:本文為CSDN博主「鄧盛余」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_35384853/article/details/100141899
可擴展性
Tokens能夠創建與其它程序共享權限的程序。例如,能將一個隨便的社交帳號和自己的大號(Fackbook或是Twitter)聯系起來。當通過服務登錄Twitter(我們將這個過程Buffer)時,我們可以將這些Buffer附到Twitter的數據流上(we are allowing Buffer to post to our Twitter stream)。
使用tokens時,可以提供可選的權限給第三方應用程序。當用戶想讓另一個應用程序訪問它們的數據,我們可以通過建立自己的API,得出特殊權限的tokens。
支持多平台跨服務器
只要用戶有一個通過了驗證的token,數據和資源就能夠在任何平台(Android,ios, h5)任何服務器上被請求到。
最后做個三者的比較:
cookie :
-
cookie由服務器生成,保存在客戶端瀏覽器。
-
容易被劫持,不安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙。
-
cookie可以被用戶禁止
-
容量小, 單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
session
-
session是由應用服務器維持的一個服務器端的存儲空間, 沒有對存儲的數據量的限制,可以保存更為復雜的數據類型.
-
session 默認被存在在服務器的一個文件里, 但是實際中可以放在 文件、數據庫、或內存中都可以。
-
當用戶量增多時,會對服務器造成較大壓力。
-
Session的實現方式大多數情況用Cookie保存的,但是也可以使用URL地址重寫。
-
較安全,用戶驗證這種場合一般會用 session, 比如金融銀行類的產品,
token
1.無狀態、可擴展
2.支持移動設備
3.跨服務器調用
4.安全
cookie,session與token的真正區別你真的了解了嗎?https://zhuanlan.zhihu.com/p/344757902