|
首先我們來說一下認(rèn)證(Authentication): 通俗的來說認(rèn)證就是?驗(yàn)證當(dāng)前用戶的身份。例如,你上班打卡,為了防止你作弊,就需要你用到你的指紋來打卡,如果打卡系統(tǒng)里面的指紋和你的指紋匹配,那就打卡成功 這樣就是通過你的指紋來證明是你本人打的卡。 在互聯(lián)網(wǎng)中也是要進(jìn)行認(rèn)證的,在互聯(lián)網(wǎng)的認(rèn)證方式有: 1.? 通過用戶名和密碼登錄 2.?郵箱發(fā)送登錄驗(yàn)證碼或者鏈接 3.?手機(jī)號接收驗(yàn)證碼 只要你有驗(yàn)證碼,那就承認(rèn)你的身份了。 ? 接下來我們說一下授權(quán)(Authorization): 授權(quán)也就是用戶授予第三方應(yīng)用訪問該用戶某些資源的權(quán)限,例如,在你安裝手機(jī)APP的時(shí)候,它就會詢問你是否允許授予權(quán)限(短信、儲存、你的地理位置等權(quán)限) 當(dāng)你訪問微信小程序,在登錄時(shí),小程序會詢問是否允許授予權(quán)限(獲取昵稱、頭像、地區(qū)、性別等個(gè)人信息) 你允許這些權(quán)限,也就是說你授權(quán)給這些應(yīng)用,讓它們擁有使用你授予的這些權(quán)限,實(shí)現(xiàn)授權(quán)的方式有: ? 接下來說一下憑證(Credentials): ? 實(shí)現(xiàn)認(rèn)證和授權(quán)的前提是需要一種媒介(證書)?來標(biāo)記訪問者的身份 在現(xiàn)實(shí)生活中,每個(gè)人都會有一張專屬的居民身份證,是用于證明持有人身份的一種法定證件。通過身份證,我們可以辦理手機(jī)卡/銀行卡/個(gè)人貸款/交通出行等等,這就是認(rèn)證的憑證。 在互聯(lián)網(wǎng)應(yīng)用中,一般網(wǎng)站(例如,博客園)會有兩種模式,游客模式和登錄模式。游客模式下,可以正常瀏覽網(wǎng)站上面的文章,一旦想要點(diǎn)贊/收藏/分享文章,就需要登錄或者注冊賬號。當(dāng)用戶登錄成功后,服務(wù)器會給該用戶使用的瀏覽器頒發(fā)一個(gè)令牌(token),這個(gè)令牌用來表明你的身份,每次瀏覽器發(fā)送請求時(shí)會帶上這個(gè)令牌,就可以使用游客模式下無法使用的功能。 ? 接下來我們來了解一下什么是?Cookie: HTTP 是一種無狀態(tài)的協(xié)議(對于事務(wù)處理沒有記憶能力,每次客戶端和服務(wù)端會話完成時(shí),服務(wù)端不會保存任何會話信息):每個(gè)請求都是完全獨(dú)立的,服務(wù)端無法確認(rèn)當(dāng)前訪問者的身份信息,無法分辨上一次的請求發(fā)送者和這一次的發(fā)送者是不是同一個(gè)人。所以服務(wù)器與瀏覽器為了進(jìn)行會話跟蹤(知道是誰在訪問我),就必須主動的去維護(hù)一個(gè)狀態(tài),這個(gè)狀態(tài)用于告知服務(wù)端前后兩個(gè)請求是否來自同一瀏覽器。而這個(gè)狀態(tài)需要通過 cookie 或者 session 去實(shí)現(xiàn)。 cookie 存儲在客戶端:?cookie 是服務(wù)器發(fā)送到用戶瀏覽器并保存在本地的一小塊數(shù)據(jù),它會在瀏覽器下次向同一服務(wù)器再發(fā)起請求時(shí)被攜帶并發(fā)送到服務(wù)器上。 cookie 不可跨域:?每個(gè) cookie 都會綁定單一的域名,無法在別的域名下獲取使用,一級域名和二級域名之間是允許共享使用的(靠的是 domain)。 cookie 屬性說明: cookie 是以鍵值對的方式存在的,例如:name=value 是一個(gè)鍵值對,設(shè)置 Cookie 的名稱及相對應(yīng)的值,都必須是字符串類型 如果值為 Unicode 字符,需要為字符編碼 如果值為二進(jìn)制數(shù)據(jù),則需要使用 BASE64 編碼。domain(域)指定 cookie 所屬域名,默認(rèn)是當(dāng)前域名path****指定 cookie 在哪個(gè)路徑(路由)下生效,默認(rèn)是 '/'。如果設(shè)置為? 比 expires 好用。expires過期時(shí)間,在設(shè)置的某個(gè)時(shí)間點(diǎn)后該 cookie 就會失效。一般瀏覽器的 cookie 都是默認(rèn)儲存的,當(dāng)關(guān)閉瀏覽器結(jié)束這個(gè)會話的時(shí)候,這個(gè) cookie 也就會被刪除secure該 cookie 是否僅被使用安全協(xié)議傳輸。安全協(xié)議有 HTTPS,SSL等,在網(wǎng)絡(luò)上傳輸數(shù)據(jù)之前先將數(shù)據(jù)加密。默認(rèn)為false。當(dāng) secure 值為 true 時(shí),cookie 在 HTTP 中是無效,在 HTTPS 中才有效。httpOnly****如果給某個(gè) cookie 設(shè)置了 httpOnly 屬性,則無法通過 JS 腳本 讀取到該 cookie 的信息,但還是能通過 Application 中手動修改 cookie,所以只是在一定程度上可以防止 XSS 攻擊,不是絕對的安全 注意問題: 因?yàn)榇鎯υ诳蛻舳?,容易被客戶端篡改,使用前需要?yàn)證合法性 不要存儲敏感數(shù)據(jù),比如用戶密碼,賬戶余額 使用 httpOnly 在一定程度上提高安全性 盡量減少 cookie 的體積,能存儲的數(shù)據(jù)量不能超過 4kb 設(shè)置正確的 domain 和 path,減少數(shù)據(jù)傳輸 cookie 無法跨域 一個(gè)瀏覽器針對一個(gè)網(wǎng)站最多存 20 個(gè)Cookie,瀏覽器一般只允許存放 300 個(gè)Cookie 移動端對 cookie 的支持不是很好,而 session 需要基于 cookie 實(shí)現(xiàn),所以移動端常用的是 token ? 接下來是Session: ? session 是另一種記錄服務(wù)器和客戶端會話狀態(tài)的機(jī)制 session 是基于 cookie 實(shí)現(xiàn)的,session 存儲在服務(wù)器端,sessionId 會被存儲到客戶端的cookie 中
? ? session 認(rèn)證流程: 1.?用戶第一次請求服務(wù)器的時(shí)候,服務(wù)器根據(jù)用戶提交的相關(guān)信息,創(chuàng)建對應(yīng)的 Session 2.?請求返回時(shí)將此 Session 的唯一標(biāo)識信息 SessionID 返回給瀏覽器 3.?瀏覽器接收到服務(wù)器返回的 SessionID 信息后,會將此信息存入到 Cookie 中,同時(shí) Cookie 記錄此 SessionID 屬于哪個(gè)域名 4.?當(dāng)用戶第二次訪問服務(wù)器的時(shí)候,請求會自動判斷此域名下是否存在 Cookie 信息,如果存在自動將 Cookie 信息也發(fā)送給服務(wù)端,服務(wù)端會從 Cookie 中獲取 SessionID,再根據(jù) SessionID 查找對應(yīng)的 Session 信息,如果沒有找到說明用戶沒有登錄或者登錄失效,如果找到 Session 證明用戶已經(jīng)登錄可執(zhí)行后面操作。 綜合以上流程可知,SessionID 是連接 Cookie 和 Session 的一道橋梁,大部分系統(tǒng)也是根據(jù)此原理來驗(yàn)證用戶登錄狀態(tài)的。 注意問題: 將 session 存儲在服務(wù)器里面,當(dāng)用戶同時(shí)在線量比較多時(shí),這些 session 會占據(jù)較多的內(nèi)存,需要在服務(wù)端定期的去清理過期的 session 當(dāng)網(wǎng)站采用集群部署的時(shí)候,會遇到多臺 web 服務(wù)器之間如何做 session 共享的問題。因?yàn)?session 是由單個(gè)服務(wù)器創(chuàng)建的,但是處理用戶請求的服務(wù)器不一定是那個(gè)創(chuàng)建 session 的服務(wù)器,那么該服務(wù)器就無法拿到之前已經(jīng)放入到 session 中的登錄憑證之類的信息了。 當(dāng)多個(gè)應(yīng)用要共享 session 時(shí),除了以上問題,還會遇到跨域問題,因?yàn)椴煌膽?yīng)用可能部署的主機(jī)不一樣,需要在各個(gè)應(yīng)用做好 cookie 跨域的處理。 sessionId 是存儲在 cookie 中的,假如瀏覽器禁止 cookie 或不支持 cookie 怎么辦??一般會把 sessionId 跟在 url 參數(shù)后面即重寫 url,所以 session 不一定非得需要靠 cookie 實(shí)現(xiàn) 移動端對 cookie 的支持不是很好,而 session 需要基于 cookie 實(shí)現(xiàn),所以移動端常用的是 token ? ? 接下來說一下Cookie 和 Session 的區(qū)別:
? ? 接下來是?Token(令牌): ? (訪問)Acesss Token : 訪問資源接口(API)時(shí)所需要的資源憑證 簡單 token 的組成:?uid(用戶唯一的身份標(biāo)識)、time(當(dāng)前時(shí)間的時(shí)間戳)、sign(簽名,token 的前幾位以哈希算法壓縮成的一定長度的十六進(jìn)制字符串) 特點(diǎn):服務(wù)端無狀態(tài)化、可擴(kuò)展性好,支持移動端設(shè)備,安全,支持跨程序調(diào)用 ? token 的身份驗(yàn)證流程:
? ?
每一次請求都需要攜帶 token,需要把 token 放到 HTTP 的 Header 里 基于 token 的用戶認(rèn)證是一種服務(wù)端無狀態(tài)的認(rèn)證方式,服務(wù)端不用存放 token 數(shù)據(jù)。用解析 token 的計(jì)算時(shí)間換取 session 的存儲空間,從而減輕服務(wù)器的壓力,減少頻繁的查詢數(shù)據(jù)庫 token 完全由應(yīng)用管理,所以它可以避開同源策略 ? ?。ㄋ⑿拢?strong>Refresh Token: refresh token 是專用于刷新 access token 的 token。如果沒有 refresh token,也可以刷新 access token,但每次刷新都要用戶輸入登錄用戶名與密碼,會很麻煩。有了 refresh token,可以減少這個(gè)麻煩,客戶端直接用 refresh token 去更新 access token,無需用戶進(jìn)行額外的操作。
? ?
注意問題: ? 如果你認(rèn)為用數(shù)據(jù)庫來存儲 token 會導(dǎo)致查詢時(shí)間太長,可以選擇放在內(nèi)存當(dāng)中。比如 redis 很適合你對 token 查詢的需求。 token 完全由應(yīng)用管理,所以它可以避開同源策略 token 可以避免 CSRF 攻擊(因?yàn)椴恍枰?cookie 了) 移動端對 cookie 的支持不是很好,而 session 需要基于 cookie 實(shí)現(xiàn),所以移動端常用的是 token ? ? 接下來說一下Token 和 Session 的區(qū)別?:? Session 是一種記錄服務(wù)器和客戶端會話狀態(tài)的機(jī)制,使服務(wù)端有狀態(tài)化,可以記錄會話信息。而 Token 是令牌,訪問資源接口(API)時(shí)所需要的資源憑證。Token?使服務(wù)端無狀態(tài)化,不會存儲會話信息。 Session 和 Token 并不矛盾,作為身份認(rèn)證 Token 安全性比 Session 好,因?yàn)槊恳粋€(gè)請求都有簽名還能防止監(jiān)聽以及重放攻擊,而 Session 就必須依賴鏈路層來保障通訊安全了。如果你需要實(shí)現(xiàn)有狀態(tài)的會話,仍然可以增加 Session 來在服務(wù)器端保存一些狀態(tài)。 所謂 Session 認(rèn)證只是簡單的把 User 信息存儲到 Session 里,因?yàn)?SessionID 的不可預(yù)測性,暫且認(rèn)為是安全的。而 Token ,如果指的是 OAuth Token 或類似的機(jī)制的話,提供的是 認(rèn)證 和 授權(quán) ,認(rèn)證是針對用戶,授權(quán)是針對 App 。其目的是讓某 App 有權(quán)利訪問某用戶的信息。這里的 Token 是唯一的。不可以轉(zhuǎn)移到其它 App上,也不可以轉(zhuǎn)到其它用戶上。Session 只提供一種簡單的認(rèn)證,即只要有此 SessionID ,即認(rèn)為有此 User 的全部權(quán)利。是需要嚴(yán)格保密的,這個(gè)數(shù)據(jù)應(yīng)該只保存在站方,不應(yīng)該共享給其它網(wǎng)站或者第三方 App。所以簡單來說:如果你的用戶數(shù)據(jù)可能需要和第三方共享,或者允許第三方調(diào)用 API 接口,用 Token 。如果永遠(yuǎn)只是自己的網(wǎng)站,自己的 App,用什么就無所謂了。 ? 下面是一些新知識:JWT JSON Web Token(簡稱 JWT)是目前最流行的跨域認(rèn)證解決方案。它是一種認(rèn)證授權(quán)機(jī)制。 JWT 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于 JSON 的開放標(biāo)準(zhǔn)(RFC 7519)。JWT 的聲明一般被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源。比如用在用戶登錄上。 可以使用 HMAC 算法或者是 RSA 的公/私秘鑰對 JWT 進(jìn)行簽名。因?yàn)閿?shù)字簽名的存在,這些傳遞的信息是可信的
? ? JWT 認(rèn)證流程: 用戶輸入用戶名/密碼登錄,服務(wù)端認(rèn)證成功后,會返回給客戶端一個(gè) JWT 客戶端將 token 保存到本地(通常使用 localstorage,也可以使用 cookie) 當(dāng)用戶希望訪問一個(gè)受保護(hù)的路由或者資源的時(shí)候,需要請求頭的 Authorization 字段中使用Bearer 模式添加 JWT,其內(nèi)容看起來是下面這樣 Authorization: Bearer復(fù)制代碼 服務(wù)端的保護(hù)路由將會檢查請求頭 Authorization 中的 JWT 信息,如果合法,則允許用戶的行為 因?yàn)?JWT 是自包含的(內(nèi)部包含了一些會話信息),因此減少了需要查詢數(shù)據(jù)庫的需要 因?yàn)?JWT 并不使用 Cookie 的,所以你可以使用任何域名提供你的 API 服務(wù)而不需要擔(dān)心跨域資源共享問題(CORS) 因?yàn)橛脩舻臓顟B(tài)不再存儲在服務(wù)端的內(nèi)存中,所以這是一種無狀態(tài)的認(rèn)證機(jī)制 JWT 的使用方式: 客戶端收到服務(wù)器返回的 JWT,可以儲存在 Cookie 里面,也可以儲存在 localStorage。 ? 方式一: ? 當(dāng)用戶希望訪問一個(gè)受保護(hù)的路由或者資源的時(shí)候,可以把它放在 Cookie 里面自動發(fā)送,但是這樣不能跨域,所以更好的做法是放在 HTTP 請求頭信息的 Authorization 字段里,使用 Bearer 模式添加 JWT。 GET /calendar/v1/events 方式二: 跨域的時(shí)候,可以把 JWT 放在 POST 請求的數(shù)據(jù)體里。 方式三: 通過 URL 傳輸,如:http://www./user?token=xxx ? 注意問題: 因?yàn)?JWT 并不依賴 Cookie 的,所以你可以使用任何域名提供你的 API 服務(wù)而不需要擔(dān)心跨域資源共享問題(CORS) JWT 默認(rèn)是不加密,但也是可以加密的。生成原始 Token 以后,可以用密鑰再加密一次。 JWT 不加密的情況下,不能將秘密數(shù)據(jù)寫入 JWT。 JWT 不僅可以用于認(rèn)證,也可以用于交換信息。有效使用 JWT,可以降低服務(wù)器查詢數(shù)據(jù)庫的次數(shù)。 JWT 最大的優(yōu)勢是服務(wù)器不再需要存儲 Session,使得服務(wù)器認(rèn)證鑒權(quán)業(yè)務(wù)可以方便擴(kuò)展。但這也是 JWT 最大的缺點(diǎn):由于服務(wù)器不需要存儲 Session 狀態(tài),因此使用過程中無法廢棄某個(gè) Token 或者更改 Token 的權(quán)限。也就是說一旦 JWT 簽發(fā)了,到期之前就會始終有效,除非服務(wù)器部署額外的邏輯。 JWT 本身包含了認(rèn)證信息,一旦泄露,任何人都可以獲得該令牌的所有權(quán)限。為了減少盜用,JWT的有效期應(yīng)該設(shè)置得比較短。對于一些比較重要的權(quán)限,使用時(shí)應(yīng)該再次對用戶進(jìn)行認(rèn)證。 JWT 適合一次性的命令認(rèn)證,頒發(fā)一個(gè)有效期極短的 JWT,即使暴露了危險(xiǎn)也很小,由于每次操作都會生成新的 JWT,因此也沒必要保存 JWT,真正實(shí)現(xiàn)無狀態(tài)。 為了減少盜用,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸,要使用 HTTPS 協(xié)議傳輸 ? ? ? Token 和 JWT 的區(qū)別:相同點(diǎn): 都是訪問資源的令牌 都可以記錄用戶的信息 都是使服務(wù)端無狀態(tài)化 都是只有驗(yàn)證成功后,客戶端才能訪問服務(wù)端上受保護(hù)的資源 區(qū)別: ? Token:服務(wù)端驗(yàn)證客戶端發(fā)送過來的 Token 時(shí),還需要查詢數(shù)據(jù)庫獲取用戶信息,然后驗(yàn)證 Token 是否有效。 JWT:將 Token 和 Payload 加密后存儲于客戶端,服務(wù)端只需要使用密鑰解密進(jìn)行校驗(yàn)(校驗(yàn)也是 JWT 自己實(shí)現(xiàn)的)即可,不需要查詢或者減少查詢數(shù)據(jù)庫,因?yàn)?JWT 自包含了用戶信息和加密的數(shù)據(jù)。 ? 轉(zhuǎn)載:https://www.cnblogs.com/hermit-gyqy/p/12875330.html ? 來源:https://www./content-4-823701.html |
|
|