1. 認(rèn)證 (Authentication) 和授權(quán) (Authorization)的區(qū)別是什么?這是一個絕大多數(shù)人都會混淆的問題。首先先從讀音上來認(rèn)識這兩個名詞,很多人都會把它倆的讀音搞混,所以我建議你先先去查一查這兩個單詞到底該怎么讀,他們的具體含義是什么。 說簡單點(diǎn)就是: 認(rèn)證 (Authentication): 你是誰。 授權(quán) (Authorization): 你有權(quán)限干什么。 稍微正式點(diǎn)(啰嗦點(diǎn))的說法就是:
這兩個一般在我們的系統(tǒng)中被結(jié)合在一起使用,目的就是為了保護(hù)我們系統(tǒng)的安全性。 2. 什么是Cookie ? Cookie的作用是什么?如何在服務(wù)端使用 Cookie ?
2.1 什么是Cookie ? Cookie的作用是什么?Cookie 和 Session都是用來跟蹤瀏覽器用戶身份的會話方式,但是兩者的應(yīng)用場景不太一樣。 維基百科是這樣定義 Cookie 的:Cookies是某些網(wǎng)站為了辨別用戶身份而儲存在用戶本地終端上的數(shù)據(jù)(通常經(jīng)過加密)。簡單來說: Cookie 存放在客戶端,一般用來保存用戶信息。 下面是 Cookie 的一些應(yīng)用案例:
2.2 如何在服務(wù)端使用 Cookie 呢?這部分內(nèi)容參考:https:///blog/cookies-spring-boot,更多如何在Spring Boot中使用Cookie 的內(nèi)容可以查看這篇文章。 1)設(shè)置cookie返回給客戶端 @GetMapping("/change-username")
public String setCookie(HttpServletResponse response) {
// 創(chuàng)建一個 cookie
Cookie cookie = new Cookie("username", "Jovan");
//設(shè)置 cookie過期時間
cookie.setMaxAge(7 * 24 * 60 * 60); // expires in 7 days
//添加到 response 中
response.addCookie(cookie);
return "Username is changed!";
}2) 使用Spring框架提供的 @GetMapping("/")
public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) {
return "Hey! My username is " + username;
}3) 讀取所有的 Cookie 值 @GetMapping("/all-cookies")
public String readAllCookies(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
return Arrays.stream(cookies)
.map(c -> c.getName() + "=" + c.getValue()).collect(Collectors.joining(", "));
}
return "No cookies";
}3. Cookie 和 Session 有什么區(qū)別?如何使用Session進(jìn)行身份驗(yàn)證?Session 的主要作用就是通過服務(wù)端記錄用戶的狀態(tài)。 典型的場景是購物車,當(dāng)你要添加商品到購物車的時候,系統(tǒng)不知道是哪個用戶操作的,因?yàn)?HTTP 協(xié)議是無狀態(tài)的。服務(wù)端給特定的用戶創(chuàng)建特定的 Session 之后就可以標(biāo)識這個用戶并且跟蹤這個用戶了。 Cookie 數(shù)據(jù)保存在客戶端(瀏覽器端),Session 數(shù)據(jù)保存在服務(wù)器端。相對來說 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要寫入 Cookie 中,最好能將 Cookie 信息加密然后使用到的時候再去服務(wù)器端解密。 那么,如何使用Session進(jìn)行身份驗(yàn)證? 很多時候我們都是通過 SessionID 來實(shí)現(xiàn)特定的用戶,SessionID 一般會選擇存放在 Redis 中。舉個例子:用戶成功登陸系統(tǒng),然后返回給客戶端具有 SessionID 的 Cookie,當(dāng)用戶向后端發(fā)起請求的時候會把 SessionID 帶上,這樣后端就知道你的身份狀態(tài)了。關(guān)于這種認(rèn)證方式更詳細(xì)的過程如下:
使用 Session 的時候需要注意下面幾個點(diǎn):
花了個圖簡單總結(jié)了一下Session認(rèn)證涉及的一些東西。 4.如果沒有Cookie的話Session還能用嗎?這是一道經(jīng)典的面試題! 一般是通過 Cookie 來保存 SessionID ,假如你使用了 Cookie 保存 SessionID的方案的話, 如果客戶端禁用了Cookie,那么Session就無法正常工作。 但是,并不是沒有 Cookie 之后就不能用 Session 了,比如你可以將SessionID放在請求的 url 里面 5.為什么Cookie 無法防止CSRF攻擊,而token可以?CSRF(Cross Site Request Forgery)一般被翻譯為 跨站請求偽造 。那么什么是 跨站請求偽造 呢?說簡單用你的身份去發(fā)送一些對你不友好的請求。舉個簡單的例子: 小壯登錄了某網(wǎng)上銀行,他來到了網(wǎng)上銀行的帖子區(qū),看到一個帖子下面有一個鏈接寫著“科學(xué)理財,年盈利率過萬”,小壯好奇的點(diǎn)開了這個鏈接,結(jié)果發(fā)現(xiàn)自己的賬戶少了10000元。這是這么回事呢?原來黑客在鏈接中藏了一個請求,這個請求直接利用小壯的身份給銀行發(fā)送了一個轉(zhuǎn)賬請求,也就是通過你的 Cookie 向銀行發(fā)出請求。 <a src="http://www./Transfer?bankId=11&money=10000">科學(xué)理財,年盈利率過萬</a> 上面也提到過,進(jìn)行Session 認(rèn)證的時候,我們一般使用 Cookie 來存儲 SessionId,當(dāng)我們登陸后后端生成一個SessionId放在Cookie中返回給客戶端,服務(wù)端通過Redis或者其他存儲工具記錄保存著這個Sessionid,客戶端登錄以后每次請求都會帶上這個SessionId,服務(wù)端通過這個SessionId來標(biāo)示你這個人。如果別人通過 cookie拿到了 SessionId 后就可以代替你的身份訪問系統(tǒng)了。 Session 認(rèn)證中 Cookie 中的 SessionId是由瀏覽器發(fā)送到服務(wù)端的,借助這個特性,攻擊者就可以通過讓用戶誤點(diǎn)攻擊鏈接,達(dá)到攻擊效果。 但是,我們使用 token 的話就不會存在這個問題,在我們登錄成功獲得 token 之后,一般會選擇存放在 local storage 中。然后我們在前端通過某些方式會給每個發(fā)到后端的請求加上這個 token,這樣就不會出現(xiàn) CSRF 漏洞的問題。因?yàn)椋词褂袀€你點(diǎn)擊了非法鏈接發(fā)送了請求到服務(wù)端,這個非法請求是不會攜帶 token 的,所以這個請求將是非法的。 需要注意的是不論是 Cookie 還是 token 都無法避免跨站腳本攻擊(Cross Site Scripting)XSS。
XSS中攻擊者會用各種方式將惡意代碼注入到其他用戶的頁面中。就可以通過腳本盜用信息比如cookie。 推薦閱讀:如何防止CSRF攻擊?—美團(tuán)技術(shù)團(tuán)隊(duì) 6. 什么是 Token?什么是 JWT?如何基于Token進(jìn)行身份驗(yàn)證?我們在上一個問題中探討了使用 Session 來鑒別用戶的身份,并且給出了幾個 Spring Session 的案例分享。 我們知道 Session 信息需要保存一份在服務(wù)器端。這種方式會帶來一些麻煩,比如需要我們保證保存 Session 信息服務(wù)器的可用性、不適合移動端(依賴Cookie)等等。 有沒有一種不需要自己存放 Session 信息就能實(shí)現(xiàn)身份驗(yàn)證的方式呢?使用 Token 即可!JWT (JSON Web Token) 就是這種方式的實(shí)現(xiàn),通過這種方式服務(wù)器端就不需要保存 Session 數(shù)據(jù)了,只用在客戶端保存服務(wù)端返回給客戶的 Token 就可以了,擴(kuò)展性得到提升。 JWT 本質(zhì)上就一段簽名的 JSON 格式的數(shù)據(jù)。由于它是帶有簽名的,因此接收者便可以驗(yàn)證它的真實(shí)性。 下面是 RFC 7519 對 JWT 做的較為正式的定義。
JWT 由 3 部分構(gòu)成:
在基于 Token 進(jìn)行身份驗(yàn)證的的應(yīng)用程序中,服務(wù)器通過
推薦閱讀: 7 什么是OAuth 2.0?OAuth 是一個行業(yè)的標(biāo)準(zhǔn)授權(quán)協(xié)議,主要用來授權(quán)第三方應(yīng)用獲取有限的權(quán)限。而 OAuth 2.0是對 OAuth 1.0 的完全重新設(shè)計(jì),OAuth 2.0更快,更容易實(shí)現(xiàn),OAuth 1.0 已經(jīng)被廢棄。詳情請見:rfc6749。 實(shí)際上它就是一種授權(quán)機(jī)制,它的最終目的是為第三方應(yīng)用頒發(fā)一個有時效性的令牌 token,使得第三方應(yīng)用能夠通過該令牌獲取相關(guān)的資源。 OAuth 2.0 比較常用的場景就是第三方登錄,當(dāng)你的網(wǎng)站接入了第三方登錄的時候一般就是使用的 OAuth 2.0 協(xié)議。 另外,現(xiàn)在OAuth 2.0也常見于支付場景(微信支付、支付寶支付)和開發(fā)平臺(微信開放平臺、阿里開放平臺等等)。 微信支付賬戶相關(guān)參數(shù): 推薦閱讀: 8 什么是 SSO?SSO(Single Sign On)即單點(diǎn)登錄說的是用戶登陸多個子系統(tǒng)的其中一個就有權(quán)訪問與其相關(guān)的其他系統(tǒng)。舉個例子我們在登陸了京東金融之后,我們同時也成功登陸京東的京東超市、京東家電等子系統(tǒng)。 9.SSO與OAuth2.0的區(qū)別OAuth 是一個行業(yè)的標(biāo)準(zhǔn)授權(quán)協(xié)議,主要用來授權(quán)第三方應(yīng)用獲取有限的權(quán)限。SSO解決的是一個公司的多個相關(guān)的自系統(tǒng)的之間的登陸問題比如京東旗下相關(guān)子系統(tǒng)京東金融、京東超市、京東家電等等。 |
|
|