asp.net core 自定義認證方式--請求頭認證

来源:https://www.cnblogs.com/weihanli/archive/2019/03/03/cutom-authentication-in-aspnetcore.html
-Advertisement-
Play Games

asp.net core 自定義認證方式 請求頭認證 Intro 最近開始真正的實踐了一些網關的東西,最近寫幾篇文章分享一下我的實踐以及遇到的問題。 本文主要介紹網關後面的服務如何進行認證。 解決思路 網關可以做一部分的認證和授權,服務內部有時候也會需要用戶的信息,這時該怎麼辦呢,我們使用的是 JW ...


asp.net core 自定義認證方式--請求頭認證

Intro

最近開始真正的實踐了一些網關的東西,最近寫幾篇文章分享一下我的實踐以及遇到的問題。

本文主要介紹網關後面的服務如何進行認證。

解決思路

網關可以做一部分的認證和授權,服務內部有時候也會需要用戶的信息,這時該怎麼辦呢,我們使用的是 JWT 認證,有一個 identity server去頒發,驗證 token,一種簡單方式可以把 token 直接往後傳,傳遞給後面的具體某個服務,後面的服務可以去 identity server 拿到公鑰信息去驗證 token 的合法性,依然可以拿到用戶的一些基本信息,但又覺得這樣後面的服務還是要依賴 identityserver 不是太好,因為認證已經在網關做掉了,後面不應該再去做認證的事情了,而且解析 JWT token 也是有一定的性能損耗,於是想把用戶的基本信息在網關認證完成之後放到請求頭中。

我們網關用的Ocelot,開源的原生 .NET 項目方便自己擴展,Ocelot 中有一個 Claims2Headers 可以把 Claims 中的信息轉換為請求頭,詳細使用參見文檔,但是實現有個bug,如果有多個值他只會取第一個,詳見issue,可以自己擴展一個 ocelot 的中間件替換掉原有的中間件。

把用戶信息放到請求頭中,後面的服務從請求頭中就可以拿到用戶的基本信息了,為了後面的服務不做過多的改動,我做了一個自定義的認證,從請求頭中拿用戶的基本信息進行認證,這樣後面的服務還是可以直接使用 User.Identity.IsAuthenticatedUser.Identity.Name 等,不需要做什麼改動。於是就有了這一根據請求頭認證的項目

實現效果

下載示例項目,在 TestWebApplication 目錄下運行 dotnet run

在瀏覽器中訪問 http://localhost:5000/api/values

使用 postman 或 fiddler (或其它你喜歡的工具)帶上 header 訪問 http://localhost:5000/api/values

with header

使用方式

使用方式可以參考示例項目

使用自定義的 HeaderAuthentication 來替代之前的認證方式,預設配置了用戶名,用戶id以及用戶角色,如果不能滿足可以在 options 中的 AdditionalHeaderToClaims 中添加更多轉換

        services.AddAuthentication(HeaderAuthenticationDefaults.AuthenticationSchema)
                .AddHeader(HeaderAuthenticationDefaults.AuthenticationSchema, options => { options.AdditionalHeaderToClaims.Add("UserEmail", ClaimTypes.Email); })
                ;

這樣就可以了,你可以下載示例項目,快速體驗,你可以直接添加下麵幾個請求頭

UserId 用戶id
UserName 用戶名稱
UserRoles 用戶角色(多個角色以 , 分割,可以在 options 里自定義多個值的分隔符

直接訪問需要授權才能訪問的資源了

現在只是初步的設想與實現,並已經驗證確實可行,代碼還有一些業務邏輯比如 UserId 現在是必須的,可以根據自己需要自行修改,最近有點忙,找時間再修改重構一下再發佈 nuget 包。如果有什麼需求或問題,歡迎一起探討。

源碼

自定義認證源碼

提供了 HeaderAuthetication 和 QueryAuthentication 兩種實現,一種使用請求頭信息認證,一種使用 QueryString 信息認證。

HeaderAuthetication 主要實現在 HeaderAuthenticationHandler

核心代碼,重寫 Authenticate 方法:

        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey(Options.UserIdHeaderName) || !Request.Headers.ContainsKey(Options.UserNameHeaderName))
            {
                return Task.FromResult(AuthenticateResult.NoResult());
            }
            var userId = Request.Headers[Options.UserIdHeaderName].ToString();
            var userName = Request.Headers[Options.UserNameHeaderName].ToString();
            var userRoles = new string[0];
            if (Request.Headers.ContainsKey(Options.UserRolesHeaderName))
            {
                userRoles = Request.Headers[Options.UserRolesHeaderName].ToString()
                    .Split(new[] { Options.Delimiter }, StringSplitOptions.RemoveEmptyEntries);
            }
            var claims = new List<Claim>()
            {
                new Claim(ClaimTypes.NameIdentifier, userId),
                new Claim(ClaimTypes.Name, userName),
            };

            if (userRoles.Length > 0)
            {
                claims.AddRange(userRoles.Select(r => new Claim(ClaimTypes.Role, r)));
            }
            if (Options.AdditionalHeaderToClaims.Count > 0)
            {
                foreach (var headerToClaim in Options.AdditionalHeaderToClaims)
                {
                    if (Request.Headers.ContainsKey(headerToClaim.Key))
                    {
                        foreach (var val in Request.Headers[headerToClaim.Key].ToString().Split(new[] { Options.Delimiter }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            claims.Add(new Claim(headerToClaim.Value, val));
                        }
                    }
                }
            }
            // claims identity 's authentication type can not be null https://stackoverflow.com/questions/45261732/user-identity-isauthenticated-always-false-in-net-core-custom-authentication
            var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));
            var ticket = new AuthenticationTicket(
                principal,
                Scheme.Name
            );
            return Task.FromResult(AuthenticateResult.Success(ticket));
        }

註意

請註意,如果使用這種方式,請確保你的服務不會被外界直接訪問,請求只能從網關或者本地調試發起。需要保證安全性,不能直接暴露到公網,才能使用這種方式。

Memo

如果有什麼問題或者意見,歡迎與我聯繫。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 創建項目 1.1 新建項目 首先新建一個項目,名為 mysite,命令如下: 運行成功,生成一些目錄: 1.2 啟動伺服器 執行成功,看到輸出如下信息: 在瀏覽器中訪問 ,看到以下信息,表示開啟成功(Django2.x 以下版本不一樣): 1.3 新建應用 現在我們新建一個應用(app),名為 ...
  • 題意 設把$n$個不同元素分成若幹個大小相等的集合的方案個數為$res$,求$m^{res}$模$10^9 401$後的餘數。 (n,m不超過2\ 10^9) 分析 可以知道,所求答案為$m^r \bmod P$其中$r=\sum_{d\mid n} \dfrac{n!}{\frac{n}{m}!^ ...
  • 複雜查詢時,單表對應的po類已不能滿足輸出結果集的映射。 所以有些時候就需要關聯查詢_一對一:通過條件查詢結果每個欄位都唯一 一對一:模型裡面有模型 一對多:模型裡面有集合 多對多:集合裡面有集合 方法一:resultType實現,要根據需求建立一個擴展類來作為resultType的類型。(詳細代碼 ...
  • If標簽:作為判斷入參來使用的,如果符合條件,則把if標簽體內的SQL拼接上。 註意:用if進行判斷是否為空時,不僅要判斷null,也要判斷空字元串‘’; Where標簽:會去掉條件中的第一個and符號。 通過if和where通過判斷可以選擇那些語句來執行,那些語句不執行,生成最終SQL語句 在第一 ...
  • 1.VS 安裝完成後,可以重新配置合適的開發環境 第一步: 第二步: 第三步: 第四步:選擇合適自己的開發環境 這裡我選擇常規,具體的可以看視窗右邊的說明 ...
  • 寫在前面 前幾時在寫業務代碼的時候,看到有用到lock這個方法的,而我竟然並不知道是做什麼用的,所以查找了許多博客文章,弄懂了百分之七八十,在此做下筆記。 感謝博客 http://www.cnblogs.com/wolf-sun/p/4209521.html 的解說,該篇博客大部分內容源自於此。 l ...
  • c#類的定義規範 欄位與屬性的比較: 欄位: 欄位主要是為類的內部做數據交換交互使用,欄位一般是private 欄位可以賦值,也可以取值 當欄位需要為外部數據提供數據的時候,請將欄位封裝為屬性,而不是使用公有欄位,這是面向對象所提倡的。 屬性: 屬性一般是向外提供數據,主要用來描述對象的靜態特征,所 ...
  • 大家好,這一篇向大家介紹ASP.NET MVC路由機制。【PS:上一篇-->6. ASP.NET MVC 5.0中的HTML Helpers【HTML幫助類】 】 路由是一個模式匹配系統,它確保你能夠將瀏覽器的請求,傳遞到控制器特定的Action方法上。路由引擎使用路由表,來將瀏覽器發送來的請求UR ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...