48.【.NET8 實戰--孢子記賬--從單體到微服務--轉向微服務】--擴展功能--集成網關--解決Refit接口調用未授權的訪問問題

我們在項目中集成了Refit,但是在調用接口時,出現了問題,提示未授權的訪問。這個問題是怎么導致的呢?我們該怎么處理呢?在這篇文章中我們一起來解決吧。

一、為什么會出現這個問題

讓我們來深入分析一下是哪里返回的未授權的訪問的提示。首先,我們采用最直接的方法:在IDE中全局搜索整個項目中包含這個提示的代碼。經過搜索,我們發現這個提示信息只存在于通用中間件ApplicationMiddleware中。

通過進一步分析代碼執行流程,我們定位到問題的根源在于 驗證網關簽名 環節未能通過驗證。為了更深入地了解這個問題,我們需要詳細檢查驗證網關簽名的方法ValidateGatewaySignature的執行過程。我們采用斷點調試的方式,在該方法的入口處設置斷點,然后通過Refit發送測試請求。當請求命中斷點時,通過調試器我們清晰地觀察到一個關鍵問題:在請求頭中完全不存在X-Gateway-Signature這個關鍵參數。這就直接導致了驗證失敗,系統返回未授權訪問的提示。

那么,為什么會出現這個問題呢?這涉及到我們系統的架構設計。在正常的訪問流程中,所有的請求都應該經過網關進行轉發和處理。但是在使用Refit進行服務間通信時,我們采用了一個不同的路徑:Refit直接從Nacos注冊中心獲取了一個健康的服務實例,然后直接向該實例發起請求。這種直接通信的方式繞過了網關,導致請求頭中缺少了網關在轉發時應該添加的X-Gateway-Signature簽名信息。

要解決這個問題,我們有一個相對簡單的解決方案:在使用Refit發起請求時,手動添加X-Gateway-Signature到請求頭中。這樣就能確保請求攜帶了必要的簽名信息,從而通過中間件的驗證。這個修改雖然簡單,但需要注意保持簽名生成的邏輯與網關端保持一致,以確保驗證能夠順利通過。

二、解決問題

為了解決這個問題,我們需要對RefitServiceCollectionExtensions這個Refit擴展類進行改造。具體來說,我們要在其中注冊一個特殊的DelegatingHandler,它將作為請求管道中的一個重要環節。這個處理器的主要職責是確保每一個通過Refit發出的請求都能攜帶必要的認證信息。它會自動為請求添加X-Gateway-Signature簽名頭,這個簽名頭是通過特定算法根據時間戳和密鑰生成的。不僅如此,為了保持系統中用戶上下文的連續性,這個處理器還會負責傳遞用戶相關的信息,比如用戶ID、用戶名等關鍵數據。通過將這個DelegatingHandler整合到Refit的請求管道中,我們可以在不影響現有業務邏輯的情況下,優雅地解決認證問題,使服務間的通信更加安全可靠。

2.1 新建DelegatingHandler

為了實現網關簽名驗證和用戶信息透傳的功能,我們需要在SP.Common類庫的Refit文件夾下創建一個專門的處理器類。這個處理器將作為請求管道中的重要一環,負責處理所有通過Refit發出的HTTP請求。我們將這個類命名為GatewaySignatureHandler,它繼承自DelegatingHandler基類。這個處理器類將在每個請求發出前自動為其添加必要的簽名信息和用戶上下文數據,確保下游服務能夠正確識別和處理這些請求。讓我們看看具體的實現代碼:

using System.Net.Http.Headers;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;namespace SP.Common.Refit;/// <summary>
/// 為所有下游 Refit 請求添加網關簽名與用戶透傳頭
/// </summary>
public class GatewaySignatureHandler : DelegatingHandler
{private readonly IHttpContextAccessor _httpContextAccessor;private readonly IConfiguration _configuration;public GatewaySignatureHandler(IHttpContextAccessor httpContextAccessor, IConfiguration configuration){_httpContextAccessor = httpContextAccessor;_configuration = configuration;}protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken){// 添加網關簽名var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();var secret = _configuration["GatewaySecret"] ?? "SP_Gateway_Secret_2024";var signature = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes($"{timestamp}.{secret}"));request.Headers.Remove("X-Gateway-Signature");request.Headers.Add("X-Gateway-Signature", signature);// 透傳用戶信息(若存在)var httpContext = _httpContextAccessor.HttpContext;var user = httpContext?.User;if (user?.Identity?.IsAuthenticated == true){var userId = user.FindFirstValue("UserId");var userName = user.FindFirstValue("UserName");var email = user.FindFirstValue("Email");if (!string.IsNullOrEmpty(userId))request.Headers.TryAddWithoutValidation("X-User-Id", userId);if (!string.IsNullOrEmpty(userName))request.Headers.TryAddWithoutValidation("X-User-Name", userName);if (!string.IsNullOrEmpty(email))request.Headers.TryAddWithoutValidation("X-User-Email", email);}// 如果上游帶了 Authorization,則透傳(有些服務可能需要)if (httpContext?.Request?.Headers?.TryGetValue("Authorization", out var authHeader) == true){if (!request.Headers.Contains("Authorization")){request.Headers.Authorization = AuthenticationHeaderValue.Parse(authHeader!);}}return await base.SendAsync(request, cancellationToken);}
}

讓我們詳細解析這段代碼的實現。處理器的核心邏輯在重寫的SendAsync方法中實現。首先,它會生成網關簽名。簽名的生成采用了時間戳和密鑰組合的方式,將當前的UTC時間戳與配置中的網關密鑰(如果未配置則使用默認值)拼接后進行Base64編碼。這個簽名會被添加到請求頭的X-Gateway-Signature字段中,用于下游服務的驗證。接下來,處理器會處理用戶信息的透傳。它首先檢查當前請求的用戶是否已認證,如果已認證,則從用戶聲明中提取用戶ID、用戶名和郵箱等信息。這些信息會被分別添加到請求頭中,使用X-User-IdX-User-NameX-User-Email等自定義頭部字段。這樣做的目的是確保下游服務能夠獲知請求的發起者信息。最后,處理器還會檢查是否存在授權頭(Authorization),如果存在且目標請求還沒有設置授權頭,則會將其透傳到下游請求中。這個功能特別適用于需要保持認證狀態的微服務調用場景。

2.2 注冊DelegatingHandler

為了使GatewaySignatureHandler生效,我們需要在Refit的服務注冊過程中添加它。具體來說,我們需要在RefitServiceCollectionExtensions類的AddRefitClient方法中注冊這個處理器。這個處理器會被添加到HTTP請求管道中,作為請求處理的一個重要環節。通過在服務注冊時配置這個處理器,我們可以確保所有的服務間通信都會自動攜帶必要的網關簽名和用戶信息,從而保證請求能夠順利通過下游服務的驗證。讓我們看看具體的實現代碼:

// more code ...
public static IHttpClientBuilder AddNacosRefitClient<TClient>(this IServiceCollection services,string serviceName,string? groupName,string? clusterName,string scheme = "http",RefitSettings? refitSettings = null)where TClient : class
{services.AddTransient<GatewaySignatureHandler>();return services.AddRefitClient<TClient>(refitSettings ?? new RefitSettings()).ConfigureHttpClient(c => c.BaseAddress = new Uri("http://placeholder")).AddHttpMessageHandler(sp => new NacosDiscoveryHandler(sp.GetRequiredService<IServiceDiscovery>(),serviceName,groupName ?? "DEFAULT_GROUP",clusterName ?? "DEFAULT",scheme,sp.GetRequiredService<ILogger<NacosDiscoveryHandler>>())).AddHttpMessageHandler<GatewaySignatureHandler>();
}
// more code ...

在上面的代碼中,我們通過兩個關鍵步驟來注冊和使用GatewaySignatureHandler。首先,services.AddTransient<GatewaySignatureHandler>()將處理器注冊為瞬態服務,這意味著每次需要時都會創建一個新的實例,這樣可以確保處理器在處理并發請求時的線程安全性。其次,.AddHttpMessageHandler<GatewaySignatureHandler>()將處理器添加到HTTP消息處理管道中,使其能夠攔截和處理所有出站的HTTP請求。這樣,每個通過Refit發出的請求都會經過這個處理器,自動獲得必要的網關簽名和用戶信息,從而確保請求能夠順利通過下游服務的驗證。

三、總結

這篇文章詳細探討了在微服務架構中使用Refit進行服務間通信時遇到的未授權訪問問題及其解決方案。通過分析,我們發現問題的根源在于Refit直接調用服務實例時繞過了網關,導致缺少必要的網關簽名驗證信息。為了解決這個問題,我們實現了一個自定義的DelegatingHandler,它能夠自動為所有Refit請求添加網關簽名和用戶信息。這個處理器不僅確保了請求能夠通過下游服務的驗證,還實現了用戶上下文的透傳,使得服務間的通信更加安全可靠。這個解決方案優雅地解決了認證問題,同時保持了代碼的整潔性和可維護性,為微服務架構中的服務間通信提供了一個實用的范例。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/920504.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/920504.shtml
英文地址,請注明出處:http://en.pswp.cn/news/920504.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

nacos登錄認證

先看一個現象bootstrap.yml配置如下&#xff1a;spring:application:name: myservicecloud:nacos:discovery:server-addr: 127.0.0.1:8848username: nacospassword: nacosconfig:prefix: testfile-extension: ymlusername: nacos123password: nacos注意&#xff1a;配置中nacos…

論文閱讀:arixv 2025 WideSearch: Benchmarking Agentic Broad Info-Seeking

WideSearch&#xff1a;大規模信息檢索基準測試 https://arxiv.org/pdf/2508.07999 字節&#xff1a;Agent大規模信息獲取基準WideSearch WideSearch&#xff1a;揭示 AI 智能體缺失的「廣度」能力 Project Page: https://widesearch-seed.github.io/ get the data&#x…

【Docker基礎】Docker-compose進階配置:資源限制與高可用部署

目錄 引言 1 Docker資源限制基礎概念 1.1 為什么需要資源限制 1.2 Docker資源限制的類型 2 CPU與內存資源限制配置 2.1 傳統資源限制方式&#xff08;version 2&#xff09; 2.2 現代資源限制方式&#xff08;version 3 deploy.resources&#xff09; 關鍵參數解釋&…

SQL優化--OR

優化 SQL 中的 OR 條件是一個非常常見的性能調優問題。OR 操作符經常會導致性能下降&#xff0c;因為它使得數據庫優化器難以高效地使用索引。下面我將從淺入深地為你講解優化 OR 的多種策略&#xff0c;并附上示例。為什么 OR 性能往往較差&#xff1f;在簡單的 WHERE 子句中&…

Java試題-選擇題(21)

Java試題-選擇題(21) 題目 有關線程的敘述正確的是 ? A:可以獲得對任何對象的互斥鎖定 B:通過繼承Thread類或實現Runnable接口,可以獲得對類中方法的互斥鎖定 C:線程通過使用synchronized關鍵字可獲得對象的互斥鎖定 D:線程調度算法是平臺獨立的 下面有關forward和re…

預測模型及超參數:3.集成學習:[1]LightGBM

想象你是一位樂隊指揮&#xff0c;你的任務是協調樂隊中的每位音樂家&#xff0c;以演奏出一場完美的音樂會。每位音樂家&#xff08;即決策樹&#xff09;擅長不同的樂器或樂章。在指揮過程中&#xff0c;你通過調節各位音樂家演奏的強度&#xff08;模型參數&#xff09;&…

Jetson進行旋轉目標檢測推理實現大疆無人機飛行控制

源碼結構 大疆PSDK源碼地址&#xff1a; https://github.com/dji-sdk/Payload-SDK其目錄結構如下&#xff1a; Payload-SDK-master ├── CMakeLists.txt ├── doc │ ├── dji_sdk_code_style │ └── simple_model ├── EULA.txt ├── LICENSE.txt ├── psd…

阿里云百煉智能體連接云數據庫實踐(DMS MCP)

這篇文章主要是通過使用阿里云的百煉智能體與阿里云的serverless來實現數據庫的操作 歡迎一起交流&#xff01;&#xff01; 首先&#xff0c;當然是選擇自己需要的數據庫啦 在阿里云控制臺選擇產品 - > 數據庫 - > 數據管理DMS進來的界面如下所示 第一次進來的時候是…

某商店JS混淆補環境與純算逆向分析

文章目錄1. 寫在前面2. 接口分析3. 補環境分析4. 純算法還原【&#x1f3e0;作者主頁】&#xff1a;吳秋霖 【&#x1f4bc;作者介紹】&#xff1a;擅長爬蟲與JS加密逆向分析&#xff01;Python領域優質創作者、CSDN博客專家、阿里云博客專家、華為云享專家。一路走來長期堅守并…

如何安裝 mysql-installer-community-8.0.21.0.tar.gz(Linux 詳細教程附安裝包下載)?

這是一個 ?Linux 下 MySQL 8.0.21 的壓縮安裝包&#xff0c;雖然名字里有 installer&#xff0c;但它其實就是一個壓縮好的二進制安裝包&#xff0c;不是 Windows 那種圖形化安裝程序。 一、準備工作 確保你已經有&#xff1a; Linux 系統&#xff08;比如 Ubuntu、CentOS、…

IDEA-琴澳研究中心及學術聯盟啟動,產研協同賦能區域發展

8月30日&#xff0c;IDEA-琴澳中心主導研發的Smaray渲染引擎將發布可免費下載的Tech Preview&#xff08;技術預覽版&#xff09;。本次發布標志著粵港澳大灣區在政產研協同創新實現成果落地&#xff0c;也是產業“人工智能”的探索邁進。Smaray是國內首個公開服務的、AI驅動的…

如何備份 TECNO 手機上的短信

許多 TECNO 用戶都在尋找方法&#xff0c;以防止因手機損壞、被盜或恢復出廠設置而導致重要對話意外丟失&#xff0c;確保在需要時能夠訪問他們的數據。還有些人希望在釋放設備存儲空間的同時&#xff0c;仍然保留舊消息的副本以供日后參考。如果你一直在尋找“備份 TECNO 短信…

OpenAI Sora深度解析:AI視頻生成技術如何重塑廣告電商行業?影業合作已落地

最近刷到一條超震撼的視頻&#xff1a;咖啡杯從桌角滑落&#xff0c;在空中轉了半圈居然自己彈回桌面&#xff0c;牛奶一滴沒灑。你猜怎么著&#xff1f;這居然是AI生成的&#xff0c;就是OpenAI那個叫Sora的工具做的。是不是覺得有點不可思議&#xff1f;現在這技術已經能做到…

力扣p1011在D天送達包裹的能力 詳解

題目如下&#xff1a;代碼如下&#xff0c;先看代碼&#xff0c;再看思路&#xff1a;注意&#xff0c;從check函數下方的left處看&#xff0c;我認為難點在于以啥來二分&#xff0c;都說求啥拿啥分&#xff0c;但實際無從下手&#xff0c;關鍵在于如何尋找邊界&#xff0c;此處…

React Three Fiber

下面&#xff0c;我們來系統的梳理關于 React Three Fiber&#xff1a;WebGL 與 React 的基本知識點&#xff1a; 一、React Three Fiber 核心概念 1.1 什么是 React Three Fiber&#xff1f; React Three Fiber&#xff08;R3F&#xff09;是一個用于 Three.js 的 React 渲染…

YARN架構解析:深入理解Hadoop資源管理核心

YARN架構解析&#xff1a;深入理解Hadoop資源管理核心 &#x1f31f; 你好&#xff0c;我是 勵志成為糕手 &#xff01; &#x1f30c; 在代碼的宇宙中&#xff0c;我是那個追逐優雅與性能的星際旅人。 ? 每一行代碼都是我種下的星光&#xff0c;在邏輯的土壤里生長成璀璨的銀…

爬蟲代理的核心作用、分類及使用要點

在數據采集場景中&#xff0c;爬蟲代理作為“中間傳輸節點”&#xff0c;通過轉發爬蟲請求、隱藏真實IP地址&#xff0c;解決傳統爬蟲面臨的諸多限制&#xff0c;其核心價值體現在三個方面&#xff1a;突破IP封鎖與訪問限制&#xff1a;多數網站會對高頻請求的IP進行封鎖&#…

EXCEL開發之路(三)sheets梯形樣式設計—仙盟創夢IDE

在蔬菜批發行業&#xff0c;高效的信息管理與操作便捷性對于業務的順暢開展至關重要。梯形 Nav&#xff08;導航欄&#xff09;切換這一設計&#xff0c;看似只是界面交互的小細節&#xff0c;實則在提升用戶體驗、優化業務流程等方面有著不可忽視的意義&#xff0c;對于初學者…

Unity游戲打包——iOS打包pod的重裝和使用

本文由 NRatel 歷史筆記整理而來&#xff0c;如有錯誤歡迎指正。 一、重裝 pod 和使用 1、下載安裝 rvm curl -L get.rvm.io | bash -s stable 2、使環境變量生效 (zsh) source ~/.zshrc source ~/.profile 3、查看rvm版本 rvm -v 4、重裝ruby 關閉mac sip&#xff08;可能需…

AWS OpenSearch 可觀測最佳實踐

AWS OpenSearch 介紹 OpenSearch 是一種全面開源搜索和分析引擎&#xff0c;使用案例包括日志分析、實時應用程序監控、點擊流分析等。Amazon OpenSearch Service 是一項托管服務&#xff0c;讓用戶能夠在 AWS 云中輕松部署、運行并擴展 OpenSearch 集群。 觀測云 觀測云是一…