ASP.NET WebAPI2第006天_API安全防範Key的設計_API Key跟Token差異

 
倘若我們設計的API任誰都能存取肯定會天下大亂

在一些公開資料平台
通常大多會設計有API金鑰的模式供他人存取,而金鑰注重在於授權機制而非身分驗證


https://www.wfublog.com/2018/12/google-api-key-activate-quota.html
就能以此識別該專案呼叫的存取數目quota還剩多少跟費用計算


而在以前接觸過的歐洲專利局OPS API存取
設計則還包含除了KEY 跟 Token等名詞

絕大部分人應該都知道

授權機制(Authorization)
the process of validating whether ‘you have right to access’ the requested resource on the system.
確認你的身份之後提供給你許可權
例如Admin User可以修改資料,而General User只能閱讀資料。


身分驗證(Authentication)
the process of validating ‘who you are’ by comparing the provided information with existing information data base of the system.
驗證使用者的身份
例如User希望以該平台會員的身份登入,那麼應用程式需要通過使用者名稱和密碼確認你真的是隸屬於此系統的會員。



API Key跟Token差異

以較廣義(不這麼嚴謹)跟通用的說法(有些其他的可能不是對應含意,先寫好避免被噴。)

API Key (金鑰)
主要是以一個專案應用、終端(手機、平板、電腦)為單位,金鑰注重在於授權機制(Authorization)白話一點可以理解為專for應用程式端所發放的
一組帳密且發放自提供API的原廠用於識別呼叫的專案 (即應用程式或網站)

可以理解生活應用中office啟用金鑰、台鐵高鐵買的票、門票
有的可能終生使用、有的則可能有有效期限。


token(使用者憑證) 或者 session key (id)
主要是以一個user登入帳戶為單位,注重在於身分驗證(Authentication)
使用者驗證:安全地驗證進行呼叫的使用者是否符合其宣稱的身分
使用者授權:檢查使用者是否擁有權限發出要求



基於驗證機制不同才又分為

Session-Based Authentication

Token-Based Authentication

還有更新穎的
Biometric-Based Authentication 生物識別(不在這次探討中)
虹膜、指紋、人臉



Session-Based Authentication(Traditional Authentication)
在早期或者說比較成熟用很久的(還是有很多舊系統或有歷史的採用此套機制)
通常流程圖如下

時序圖




當請求發出後會將帳密(密碼多半會做雜湊不會直接明碼傳輸)
跟來自DB查詢結果做比對若有成功驗證過關則產生一組session存放於Server的memory中
供其存取相關帳戶資訊
而通常會傳送session id(key)至Client端cookies中
即再下一次request會帶上該cookie以利server端驗證session資料
(Session 機制會在一個用戶完成身分認證後,存下所需的用戶資料,接著產生一組對應的對應的id,存入 cookie 後傳回用戶端。)




缺點:

1.當然缺點就是無法跨server,也會造成server loading過重。
session將狀態儲存在伺服器端,佔用伺服器記憶體,如果使用者量過大,會嚴重影響伺服器的效能。


2.還有就是在於當browser若關閉或禁用cookie
session就會有無法正常work的狀況當然還有其他不是這麼好的備案
由於伺服器在預設情況下,會使用Cookie的方式將SessionId傳送給瀏覽器,
因此當使用者禁止Cookie,則SessionId不會被瀏覽器儲存
此時,伺服器可以使用如URL重寫(就是把session id直接附加在URL路徑)
這樣的方式來發送SessionId
而安全性問題就可能衍伸出後續Session Fixation Attack。



Token-Based Authentication
目前主流是JWT (JSON Web Token)
JWT 是一套基於 JSON 的開放標準 (RFC 7519),透過HMAC、RSA、ECDS等演算法進行加密。
經常用於對使用者進行驗證,也就是使用者會先請求身分提供的伺服器給予該JWT,而後,只要使用者帶著這個JWT向資源伺服器請求資源,如果這個JWT是有效的,那麼就能獲取資源



時序圖


其優點就在於
1.可以跨Server存取不會像session侷限單一台Server
token 自身包含了身份驗證所需要的所有資訊,使得我們的伺服器不需要儲存 Session 資訊,增加了系統的可用性和伸縮性,大大減輕了服務端的壓力。因此有大型網路流量或者用戶數較多的一些B2C應用可能較常採用此技術,主要能配合分散Server Loading架構。

2.基於安全性層面
防止CSRF跨站請求偽造

3.較適合移動端應用(或者使用者終端、客戶端非browser而是手機APP或桌面APP等情境)
使用 Session 進行身份認證的話,需要儲存一份資訊在伺服器端,而且這種方式會依賴到 Cookie(需要 Cookie 儲存 SessionId),所以不適合移動端。
但是,使用 token 進行身份認證就不會存在這種問題,因為只要 token 可以被客戶端儲存就能夠使用,而且 token 還可以跨語言使用。


在web api專案中產生
ApiKeyMessageHandler

使該class 繼承自DelegatingHandler (需引入命名空間System.Net.Http   )


A message handler is a class that receives an HTTP request and returns an HTTP response. Message handlers derive from the abstract HttpMessageHandler class.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace MyWebAPI2_Test0.MessageHandler
{
    public class ApiKeyMessageHandler : DelegatingHandler
    {
        private const string ApiKeyToCheck = "A1362BNDKL3327655968974SZNBVJHKLHHFLHLKF";
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            bool validKey = false;
            IEnumerable<string> requestHeaders;
            var checkApiExists = request.Headers.TryGetValues("ApiKey", out requestHeaders);
            if (checkApiExists)
            {
                if (requestHeaders.FirstOrDefault().Equals(ApiKeyToCheck))
                {
                    validKey = true;
                }
            }
            if (!validKey)
            {
                return request.CreateResponse(HttpStatusCode.Forbidden, "Api Key Not valid");
            }
            return await base.SendAsync(request, cancellationToken);
        }
    }
}


將自己客製的MessageHandler配置到web api應用中
至Global.asax程式檔案中

Global.asax.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
using MyWebAPI2_Test0.MessageHandler;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Routing;

namespace MyWebAPI2_Test0
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            GlobalConfiguration.Configuration.MessageHandlers.Add(new ApiKeyMessageHandler());
        }
    }
}


而若我們重新呼叫查詢產品列表的api會發覺突然有被卡關


此時就是api key已經開始有防禦機制
需要再Header額外增加我們自訂的key-value pair











Ref:
HTTP Message Handlers in ASP.NET Web API























留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header