ASP.NET Core Web Api之JWT(一)
最近沉寂了一段,主要是上半年相當于休息和調整了一段時間,接下來我將開始陸續學習一些新的技能,比如Docker、Jenkins等,都會以生活實例從零開始講解起,到時一并和大家分享和交流。接下來幾節課的內容將會講解JWT,關于JWT的原理解析等等大有文章,就不再敘述,這里我們講解使用和一些注意的地方。
在.NET Core之前對于Web應用程序跟蹤用戶登錄狀態最普通的方式則是使用Cookie,當用戶點擊登錄后將對其信息進行加密并響應寫入到用戶瀏覽器的Cookie里,當用戶進行請求時,服務端將對Cookie進行解密,然后創建用戶身份,整個過程都是那么順其自然,但是這是客戶端是基于瀏覽器的情況,如果是客戶端是移動app或者桌面應用程序呢?關于JWT原理可以參考系列文章https://www.cnblogs.com/RainingNight/p/jwtbearer-authentication-in-asp-net-core.html,當然這只是其中一種限制還有其他。如果我們使用Json Web Token簡稱為JWT而不是使用Cookie,此時Token將代表用戶,同時我們不再依賴瀏覽器的內置機制來處理Cookie,我們僅僅只需要請求一個Token就好。這個時候就涉及到Token認證,那么什么是Token認證呢?一言以蔽之:將令牌(我們有時稱為AccessToken或者是Bearer Token)附加到HTTP請求中并對其進行身份認證的過程。Token認證被廣泛應用于移動端或SPA。
JWT由三部分構成,Base64編碼的Header,Base64編碼的Payload,簽名,三部分通過點隔開。第一部分以Base64編碼的Header主要包括Token的類型和所使用的算法,例如:
第二部分以Base64編碼的Payload主要包含的是聲明(Claims),例如,如下:
第三部分則是將Key通過對應的加密算法生成簽名,最終三部分以點隔開,比如如下形式:
到這里此時我們應該知道:JWT包含的信息并沒有加密,比如為了獲取Payload,我們大可通過比如谷歌控制臺中的APi(atob)對其進行解碼,如下:
那如我所說既然JWT包含的信息并沒有加密,只是進行了Base64編碼,豈不是非常不安全呢?當然不是這樣,還沒說完,第三部分就是簽名,雖然我們對Payload(姑且翻譯為有效負載),未進行加密,但是若有蓄意更換Payload,此時簽名將能充分保證Token無效,除非將簽名的Key不小心暴露在光天化日之下,否則必須是安全的。好了,到了這里,我們稍稍講解了下JWT構成,接下來我們進入如何在.NET Core中使用JWT。
在.NET Core中如何使用JWT,那么我們必須得知曉如何創建JWT,接下來我們首先創建一個端口號為5000的APi,創建JWT,然后我們需要安裝?System.IdentityModel.Tokens.Jwt?包,如下:
我們直接給出代碼來創建Token,然后一一對其進行詳細解釋,代碼如下:
如上我們在聲明集合中初始化聲明時,我們使用了兩種方式,一個是使用ClaimTypes,一個是?JwtRegisteredClaimNames?,那么這二者有什么區別?以及我們到底應該使用哪種方式更好?或者說兩種方式都使用是否有問題呢?針對ClaimTypes則來自命名空間System.Security.Claims?,而JwtRegisteredClaimNames則來自命名空間System.IdentityModel.Tokens.Jwt?,二者在獲取聲明方式上是不同的,ClaimTypes是沿襲微軟提供獲取聲明的方式,比如我們要在控制器Action方法上獲取上述ClaimTypes.Name的值,此時我們需要F12查看Name的常量定義值是多少,如下:
接下來則是獲取聲明Name的值,如下:
那么如果我們想要獲取聲明JwtRegisterClaimNames.Sub的值,我們是不是應該如上同樣去獲取呢?我們來試試。
此時我們發現為空沒有獲取到,這是為何呢?這是因為獲取聲明的方式默認是走微軟定義的一套映射方式,如果我們想要走JWT映射聲明,那么我們需要將默認映射方式給移除掉,在對應客戶端Startup構造函數中,添加如下代碼:
如果用過并熟悉IdentityServer4的童鞋關于這點早已明了,因為在IdentityServer4中映射聲明比如用戶Id即(sub)是使用的JWT,也就是說使用的JwtRegisteredClaimNames,此時我們再來獲取Sub看看。
所以以上對于初始化聲明兩種方式的探討并沒有用哪個更好,因為對于使用ClaimTypes是沿襲以往聲明映射的方式,如果要出于兼容性考慮,可以結合兩種聲明映射方式來使用。接下來我們來看生成簽名代碼,生成簽名是如下代碼:
如上我們給出簽名的Key是1234567890123456,是不是給定Key的任意長度皆可呢,顯然不是,關于Key的長度至少是16,否則會拋出如下錯誤
接下來我們再來看實例化Token的參數,即如下代碼:
issuer代表頒發Token的Web應用程序,audience是Token的受理者,如果是依賴第三方來創建Token,這兩個參數肯定必須要指定,因為第三方本就不受信任,如此設置這兩個參數后,我們可驗證這兩個參數。要是我們完全不關心這兩個參數,可直接使用JwtSecurityToken的構造函數來創建Token,如下:
這里需要注意的是Exp和Nbf是基于Unix時間的字符串,所以上述通過實例化DateTimeOffset來創建基于Unix的時間。到了這里,我們已經清楚的知道如何創建Token,接下來我們來使用Token獲取數據。我們新建一個端口號為5001的Web應用程序,同時安裝包【Microsoft.AspNetCore.Authentication.JwtBearer】接下來在Startup中ConfigureServices添加如下代碼:
如上述若Token依賴于第三方而創建,此時必然會配置issuer和audience,同時在我方也如上必須驗證issuer和audience,上述我們也驗證了簽名,我們通過設置ValidateLifetime為true,說明驗證過期時間而并非Token中的值,最后設置?ClockSkew?有效期為5分鐘。對于設置?ClockSkew??除了如上方式外,還可如下設置默認也是5分鐘。
如上對于認證方案我們使用的是?JwtBearerDefaults.AuthenticationScheme?即Bearer,除此之外我們也可以自定義認證方案名稱,如下:
最后別忘記添加認證中間件在Configure方法中,認證中間件必須放在使用MVC中間件之前,如下:
到了這里,我們通過端口為5000的Web Api創建了Token,并配置了端口號為5001的Web應用程序使用JWT認證,接下來最后一步則是調用端口號為5000的APi獲取Token,并將Token設置到請求頭中Authorization鍵的值,格式如下(注意Bearer后面有一個空格):
我們在頁面上放置一個按鈕點擊獲取端口號為5000的Token后,接下來請求端口號為5001的應用程序,如下:
本節我們講解了在.NET Core中使用JWT進行認證以及一點點注意事項,比較基礎性的東西,下一節講解完在JWT中使用刷新Token,開始正式進入Docker系列,感謝閱讀,下節見。
總結
以上是生活随笔為你收集整理的ASP.NET Core Web Api之JWT(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你必须知道的Docker镜像仓库的搭建
- 下一篇: 撸过一万行代码,你看过这篇文章吗?