硬核總結 9 個關於認證授權常見的面試題!看看自己能回答幾個!

大家好,我是Guide哥!相信很多人對認證授權方面都不是特別瞭解,搞不清Session認證、JWT以及 Cookie 這些概念。所以,根據我根據日常對這部分學習已經在項目中的實際運用總結了這8 個相關的問題並且附上了詳細的回答。

這篇文章已經參加原力計劃,覺額不錯的朋友多多點贊轉發啊!愛你們

所有問題如下,開始看答案之前不妨自己測驗一下自己究竟能回答幾個。

  1. 認證 (Authentication) 和授權 (Authorization)的區別是什麼?
  2. 什麼是Cookie ? Cookie的作用是什麼?如何在服務端使用 Cookie ?
  3. Cookie 和 Session 有什麼區別?如何使用Session進行身份驗證?
  4. 如果沒有Cookie的話Session還能用嗎?
  5. 爲什麼Cookie 無法防止CSRF攻擊,而token可以?
  6. 什麼是 Token?什麼是 JWT?如何基於Token進行身份驗證?
  7. 什麼是OAuth 2.0?
  8. 什麼是 SSO?
  9. SSO與OAuth2.0的區別

1. 認證 (Authentication) 和授權 (Authorization)的區別是什麼?

這是一個絕大多數人都會混淆的問題。首先先從讀音上來認識這兩個名詞,很多人都會把它倆的讀音搞混,所以我建議你先先去查一查這兩個單詞到底該怎麼讀,他們的具體含義是什麼。

說簡單點就是:

認證 (Authentication): 你是誰。

授權 (Authorization): 你有權限幹什麼。

稍微正式點(囉嗦點)的說法就是:

  • Authentication(認證) 是驗證您的身份的憑據(例如用戶名/用戶ID和密碼),通過這個憑據,系統得以知道你就是你,也就是說系統存在你這個用戶。所以,Authentication 被稱爲身份/用戶驗證。
  • Authorization(授權) 發生在 Authentication(認證) 之後。授權嘛,光看意思大家應該就明白,它主要掌管我們訪問系統的權限。比如有些特定資源只能具有特定權限的人才能訪問比如admin,有些對系統資源操作比如刪除、添加、更新只能特定人才具有。

這兩個一般在我們的系統中被結合在一起使用,目的就是爲了保護我們系統的安全性。

2. 什麼是Cookie ? Cookie的作用是什麼?如何在服務端使用 Cookie ?

2.1 什麼是Cookie ? Cookie的作用是什麼?

Cookie 和 Session都是用來跟蹤瀏覽器用戶身份的會話方式,但是兩者的應用場景不太一樣。

維基百科是這樣定義 Cookie 的:Cookies是某些網站爲了辨別用戶身份而儲存在用戶本地終端上的數據(通常經過加密)。簡單來說: Cookie 存放在客戶端,一般用來保存用戶信息

下面是 Cookie 的一些應用案例:

  1. 我們在 Cookie 中保存已經登錄過的用戶信息,下次訪問網站的時候頁面可以自動幫你登錄的一些基本信息給填了。除此之外,Cookie 還能保存用戶首選項,主題和其他設置信息。
  2. 使用Cookie 保存 session 或者 token ,向後端發送請求的時候帶上 Cookie,這樣後端就能取到session或者token了。這樣就能記錄用戶當前的狀態了,因爲 HTTP 協議是無狀態的。
  3. Cookie 還可以用來記錄和分析用戶行爲。舉個簡單的例子你在網上購物的時候,因爲HTTP協議是沒有狀態的,如果服務器想要獲取你在某個頁面的停留狀態或者看了哪些商品,一種常用的實現方式就是將這些信息存放在Cookie

2.2 如何在服務端使用 Cookie 呢?

這部分內容參考:https://attacomsian.com/blog/cookies-spring-boot,更多如何在Spring Boot中使用Cookie 的內容可以查看這篇文章。

1)設置cookie返回給客戶端

@GetMapping("/change-username")
public String setCookie(HttpServletResponse response) {
    // 創建一個 cookie
    Cookie cookie = new Cookie("username", "Jovan");
    //設置 cookie過期時間
    cookie.setMaxAge(7 * 24 * 60 * 60); // expires in 7 days
    //添加到 response 中
    response.addCookie(cookie);

    return "Username is changed!";
}

2) 使用Spring框架提供的@CookieValue註解獲取特定的 cookie的值

@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 有什麼區別?如何使用Session進行身份驗證?

Session 的主要作用就是通過服務端記錄用戶的狀態。 典型的場景是購物車,當你要添加商品到購物車的時候,系統不知道是哪個用戶操作的,因爲 HTTP 協議是無狀態的。服務端給特定的用戶創建特定的 Session 之後就可以標識這個用戶並且跟蹤這個用戶了。

Cookie 數據保存在客戶端(瀏覽器端),Session 數據保存在服務器端。相對來說 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要寫入 Cookie 中,最好能將 Cookie 信息加密然後使用到的時候再去服務器端解密。

那麼,如何使用Session進行身份驗證?

很多時候我們都是通過 SessionID 來實現特定的用戶,SessionID 一般會選擇存放在 Redis 中。舉個例子:用戶成功登陸系統,然後返回給客戶端具有 SessionID 的 Cookie,當用戶向後端發起請求的時候會把 SessionID 帶上,這樣後端就知道你的身份狀態了。關於這種認證方式更詳細的過程如下:

Session Based Authentication flow

  1. 用戶向服務器發送用戶名和密碼用於登陸系統。
  2. 服務器驗證通過後,服務器爲用戶創建一個 Session,並將 Session信息存儲 起來。
  3. 服務器向用戶返回一個 SessionID,寫入用戶的 Cookie。
  4. 當用戶保持登錄狀態時,Cookie 將與每個後續請求一起被髮送出去。
  5. 服務器可以將存儲在 Cookie 上的 Session ID 與存儲在內存中或者數據庫中的 Session 信息進行比較,以驗證用戶的身份,返回給用戶客戶端響應信息的時候會附帶用戶當前的狀態。

使用 Session 的時候需要注意下面幾個點:

  1. 依賴Session的關鍵業務一定要確保客戶端開啓了Cookie。
  2. 注意Session的過期時間

花了個圖簡單總結了一下Session認證涉及的一些東西。

另外,Spring Session提供了一種跨多個應用程序或實例管理用戶會話信息的機制。如果想詳細瞭解可以查看下面幾篇很不錯的文章:

4.如果沒有Cookie的話Session還能用嗎?

這是一道經典的面試題!

一般是通過 Cookie 來保存 SessionID ,假如你使用了 Cookie 保存 SessionID的方案的話, 如果客戶端禁用了Cookie,那麼Seesion就無法正常工作。

但是,並不是沒有 Cookie 之後就不能用 Session 了,比如你可以將SessionID放在請求的 url 裏面https://javaguide.cn/?session_id=xxx 。這種方案的話可行,但是安全性和用戶體驗感降低。當然,爲了你也可以對 SessionID 進行一次加密之後再傳入後端。

5.爲什麼Cookie 無法防止CSRF攻擊,而token可以?

**CSRF(Cross Site Request Forgery)**一般被翻譯爲 跨站請求僞造 。那麼什麼是 跨站請求僞造 呢?說簡單用你的身份去發送一些對你不友好的請求。舉個簡單的例子:

小壯登錄了某網上銀行,他來到了網上銀行的帖子區,看到一個帖子下面有一個鏈接寫着“科學理財,年盈利率過萬”,小壯好奇的點開了這個鏈接,結果發現自己的賬戶少了10000元。這是這麼回事呢?原來黑客在鏈接中藏了一個請求,這個請求直接利用小壯的身份給銀行發送了一個轉賬請求,也就是通過你的 Cookie 向銀行發出請求。

<a src=http://www.mybank.com/Transfer?bankId=11&money=10000>科學理財,年盈利率過萬</>

上面也提到過,進行Session 認證的時候,我們一般使用 Cookie 來存儲 SessionId,當我們登陸後後端生成一個SessionId放在Cookie中返回給客戶端,服務端通過Redis或者其他存儲工具記錄保存着這個Sessionid,客戶端登錄以後每次請求都會帶上這個SessionId,服務端通過這個SessionId來標示你這個人。如果別人通過 cookie拿到了 SessionId 後就可以代替你的身份訪問系統了。

Session 認證中 Cookie 中的 SessionId是由瀏覽器發送到服務端的,藉助這個特性,攻擊者就可以通過讓用戶誤點攻擊鏈接,達到攻擊效果。

但是,我們使用 token 的話就不會存在這個問題,在我們登錄成功獲得 token 之後,一般會選擇存放在 local storage 中。然後我們在前端通過某些方式會給每個發到後端的請求加上這個 token,這樣就不會出現 CSRF 漏洞的問題。因爲,即使有個你點擊了非法鏈接發送了請求到服務端,這個非法請求是不會攜帶 token 的,所以這個請求將是非法的。

需要注意的是不論是 Cookie 還是 token 都無法避免跨站腳本攻擊(Cross Site Scripting)XSS。

跨站腳本攻擊(Cross Site Scripting)縮寫爲 CSS 但這會與層疊樣式表(Cascading Style Sheets,CSS)的縮寫混淆。因此,有人將跨站腳本攻擊縮寫爲XSS。

XSS中攻擊者會用各種方式將惡意代碼注入到其他用戶的頁面中。就可以通過腳本盜用信息比如cookie。

推薦閱讀:

  1. 如何防止CSRF攻擊?—美團技術團隊

6. 什麼是 Token?什麼是 JWT?如何基於Token進行身份驗證?

我們在上一個問題中探討了使用 Session 來鑑別用戶的身份,並且給出了幾個 Spring Session 的案例分享。 我們知道 Session 信息需要保存一份在服務器端。這種方式會帶來一些麻煩,比如需要我們保證保存 Session 信息服務器的可用性、不適合移動端(依賴Cookie)等等。

有沒有一種不需要自己存放 Session 信息就能實現身份驗證的方式呢?使用 Token 即可!JWT (JSON Web Token) 就是這種方式的實現,通過這種方式服務器端就不需要保存 Session 數據了,只用在客戶端保存服務端返回給客戶的 Token 就可以了,擴展性得到提升。

JWT 本質上就一段簽名的 JSON 格式的數據。由於它是帶有簽名的,因此接收者便可以驗證它的真實性。

下面是 RFC 7519 對 JWT 做的較爲正式的定義。

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. ——JSON Web Token (JWT)

JWT 由 3 部分構成:

  1. Header :描述 JWT 的元數據。定義了生成簽名的算法以及 Token 的類型。
  2. Payload(負載):用來存放實際需要傳遞的數據
  3. Signature(簽名):服務器通過PayloadHeader和一個密鑰(secret)使用 Header 裏面指定的簽名算法(默認是 HMAC SHA256)生成。

在基於 Token 進行身份驗證的的應用程序中,服務器通過PayloadHeader和一個密鑰(secret)創建令牌(Token)並將 Token 發送給客戶端,客戶端將 Token 保存在 Cookie 或者 localStorage 裏面,以後客戶端發出的所有請求都會攜帶這個令牌。你可以把它放在 Cookie 裏面自動發送,但是這樣不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization字段中:Authorization: Bearer Token

Token Based Authentication flow

  1. 用戶向服務器發送用戶名和密碼用於登陸系統。
  2. 身份驗證服務響應並返回了簽名的 JWT,上面包含了用戶是誰的內容。
  3. 用戶以後每次向後端發請求都在Header中帶上 JWT。
  4. 服務端檢查 JWT 並從中獲取用戶相關信息。

推薦閱讀:

7 什麼是OAuth 2.0?

OAuth 是一個行業的標準授權協議,主要用來授權第三方應用獲取有限的權限。而 OAuth 2.0是對 OAuth 1.0 的完全重新設計,OAuth 2.0更快,更容易實現,OAuth 1.0 已經被廢棄。詳情請見:rfc6749

實際上它就是一種授權機制,它的最終目的是爲第三方應用頒發一個有時效性的令牌 token,使得第三方應用能夠通過該令牌獲取相關的資源。

OAuth 2.0 比較常用的場景就是第三方登錄,當你的網站接入了第三方登錄的時候一般就是使用的 OAuth 2.0 協議。

另外,現在OAuth 2.0也常見於支付場景(微信支付、支付寶支付)和開發平臺(微信開放平臺、阿里開放平臺等等)。

微信支付賬戶相關參數:

推薦閱讀:

8 什麼是 SSO?

SSO(Single Sign On)即單點登錄說的是用戶登陸多個子系統的其中一個就有權訪問與其相關的其他系統。舉個例子我們在登陸了京東金融之後,我們同時也成功登陸京東的京東超市、京東家電等子系統。

9.SSO與OAuth2.0的區別

OAuth 是一個行業的標準授權協議,主要用來授權第三方應用獲取有限的權限。SSO解決的是一個公司的多個相關的自系統的之間的登陸問題比如京東旗下相關子系統京東金融、京東超市、京東家電等等。

參考

  • https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4
  • https://www.varonis.com/blog/what-is-oauth/
  • https://tools.ietf.org/html/rfc6749
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章