認證授權——概念詳解

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

這兩個單詞長得很像,而且經常放在一起說。所以很多人可能以爲是一件事。其實並不是。這是兩個概念。簡單點說;

  • 認證(Authentication):你是誰
  • 授權(Authorization):你有權限幹什麼

稍微正式一點的解釋:

  • 認證(Authentication):驗證您的身份的憑據。通過這個憑據,系統知道你是誰。所以Authentication也被稱爲身份/用戶驗證。
  • 授權(Authorization):授權是在認證之後,主要掌管我們訪問系統的權限。

其實我們可以簡單的理解成認證算是身份證。證明你是誰的一個過程。而授權可以理解成你這個人的權限,比如說你可以進自己家。你可以去你的單位上班。這些權限的前提是你是你。所以認證是前提,授權是基於認證之後的。
這兩個我們一般都會結合使用,爲了保證我們系統的安全性。

RBAC模型

系統權限控制最常採用的訪問控制模型就是RBAC模型。
什麼是RBAC呢?Role-Based Access Control。
RBAC即基於角色的權限訪問控制。這是一種通過角色關聯權限,角色同時又關聯用戶的授權方式。
打個比方,在中國警察這個角色可以帶槍。而A是警察,我們從而知道A可以帶槍。
其實A是用戶,警察是角色,帶槍是權限。額RBAC就是這種通過角色來關聯用戶和權限的。當然了用戶和角色,角色和權限都是多對多的關係。
比如 警察可以帶槍,可以開警車,可以抓賊。
然後A可以是警察,B也可以是警察,C也可以是。
並且A除了是警察還可以是他孩子的父親(可以抓賊,可以帶孩子玩,可以輔導孩子寫作業,還可以打孩子),他妻子的老公(可以抓賊,可以親妻子,可以和妻子擁抱,可以和妻子一起睡)。
由此可以看出,用戶和角色,角色和權限都是多對多的關係。
上面的是理論,下面落到實際其實就是五張表的事(我直接借用現成的圖了):



三張表表分別是用戶表,角色表,菜單表。兩張關聯表就形成了這個權限控制。
我們抽取共性創建一個角色併爲之賦予對應的權限。然後把用戶設置成這個權限就可以了。

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

其實說到Cookie就不得不提Session。都是用來跟蹤瀏覽器用戶身份的會話方式。但是兩者的區別是Cookie存在客戶端,Session存在服務端。


如何在項目中使用Cookie

所有的例子都是spring boot項目。
設置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!";
}

使用spring框架提供的@CookieValue獲取指定的Cookie的值

@GetMapping("/")
public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) {
    return "Hey! My username is " + username;
}

讀取所有的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";
}

如何使用Session-Cookie方案進行身份驗證

上面說過了Cookie存在於客戶端,Session存在於服務端。而實際上我們使用的時候是二者都用的。舉個例子:

  1. 用戶成功登錄,服務器爲用戶創建一個Session,並將需要的信息存儲起來(包括不限於用戶名,用戶角色,用戶菜單權限,用戶數據權限等)。
  2. 服務器返回給客戶端一個SessionId。寫入Cookie
  3. 當用戶保存登錄狀態時,每次請求帶上Cookie,Cookie裏有SessionId
  4. 服務器獲取SessionId與存儲在內存或者數據庫中的session進行比較,以驗證用戶的身份。返回給用戶客戶端響應信息的時候會附帶用戶當前的狀態。

以上需要注意的有兩點:

  1. session的過期時間。
  2. 要確保客戶端開啓了Cookie。

多服務器節點下Session-Cookie方案如何做

在單體環境中Session-Cookie方案非常好實現,但是當服務器水平擴展成多節點,Session-Cookie方案就有挑戰了。
比如說我們有A,B兩個節點。用戶登錄請求了A,Session存在A服務器中。第二次請求B服務器,B中是沒有Session信息的,就還需要用戶登錄。
其實這種情景有多種處理方式:

  1. 用hash算法確保一個用戶的請求必然落在固定的服務器上。
    這種做法一個節點宕機需要重新登錄。
  2. 服務器之間的Session信息同步。
    這種做法成本比較大,而且節點越多成本越高。
  3. 使用單獨的服務器存儲session。
    比較常用的一種做法

如果沒有Cookie的話Session還能用麼

其實這個是可以的。Cookie是一個客戶端存儲的地方。如果不用Cookie的話,我們完全可以把這個id設置成消息頭,或者說作爲一個固定參數都可以。當然了這種方式安全性不是那麼高。

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

CSRF是跨站請求僞造。什麼是跨站請求僞造呢?就是用你的身份去發送一些不友好的請求。比如下面某個網上銀行的帖子區有這麼一個鏈接。當用戶點擊這個鏈接的時候會偷摸調用轉賬的請求。如下:

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

注意Cookie中存着SessionId。而Cookie是存在瀏覽器中的。也就是說你在這個頁面訪問這個域名下的地址,都會自動把Cookie帶上。所以你點擊如上鍊接的時候,銀行會以爲你主動調用轉賬接口,從而實現轉賬(不要槓轉賬還需要輸入密碼啥的)

但是如果使用Token的話,登錄成功獲取token後,一般我們都會存在localStorage中。然後我們前端在請求中會做全局配置自動加上這個token。所以可以防止上面這種情況(因爲這個鏈接沒走前端的處理,不會加上token)

什麼是Token?什麼是JWT?

我們上面說了Session來鑑別用戶的身份,也學會了基本的使用。但是其實這個需要客戶端服務端都存儲信息,而且依賴Cookie,不適合移動端。所以後來有了一種不需要自己存放Session信息就能實現身份驗證的方式。
我們基於Token來做身份驗證即可。我們這裏說的AccessToken指的是訪問資源接口(api)時所需要的憑證。比方說訪問Github的一些api的時候,需要帶上一個Token來表明你有訪問權。
JWT(Json web Token)是目前最流行的跨域認證解決方案。是一種基於token 的認證授權機制。JWT本身也是token,不過是一種規範化之後的JSON結構的Token。

什麼是SSO?

SSO(Single Sign On)即單點登錄。說明用戶登錄多個子系統的其中一個就有權限訪問與其相關的其它系統。這個我最近正好在做。比如說美團,我們登錄美團以後,可以在首頁點進美團外賣,美團打車,美團騎行等子系統。而之所以我們叫它們子系統是因爲這些系統也有單獨的門戶。比如說美團外賣是一個單獨的app。

什麼是OAuth 2.0?

OAuth是一個行業的標準授權協議。主要是用來授權第三方應用獲取有限的權限。
實際上它就是一種授權機制,最終目的是爲第三方應用頒發一個有時效性的令牌token,使得第三方應用能夠通過該令牌獲取相關的資源。
OAuth比較常用的場景就是第三方登錄。現在也比較常見於支付場景。

這篇筆記就記到這裏吧,感覺好多概念都講了,但是可能沒講的那麼透,JWT和SSO我都打算單獨整理。最近工作也在做SSO,所以摻雜了很多自己的理解和白話。如果有說的不準確的歡迎指出,之後我會試着整理一些落地的東西,稍微幫到你了記得點個喜歡點個關注。也祝大家工作順順利利!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章