日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 搭配 Nginx 的真实IP问题

發(fā)布時間:2023/12/4 asp.net 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 搭配 Nginx 的真实IP问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一.前言

Nginx(Engine X)是一個高性能HTTP和反向代理服務,是由俄羅斯人伊戈爾·賽索耶夫為訪問量第二的Rambler.ru站點(俄文:Рамблер)開發(fā)的,第一個公開版本0.1.0發(fā)布于2004年10月4日。 如果你是一名 ASP.NET Core 開發(fā)人員,并且你的 ASP.NET Core 應用部署在Linux上,相信你應該或多或少與 Nginx 有過接觸,在我們將 ASP.NET Core 部署在 Linux 上時,它是被用做反向代理的最好選擇之一。今天和大家聊一聊當我們使用了 Nginx 反向代理后,我們程序中獲取真實IP(客戶端真實ip,本文簡稱“真實IP”)的問題。

二.發(fā)現(xiàn)問題

1.安裝 Nginx

這里我就選用我安裝在 CentOS 7.2 上的 Nginx,在 CentOS 安裝 Nginx 的同學可以參考我以前寫的文章:CentOS 7 源碼編譯安裝?Nginx

2.新建 ASP.NET Core 項目

第一步:

第二步:

3.編寫代碼

編輯?ValuesController

? ? ? ?private readonly HttpContext _context; ? ? ? ?public ValuesController(IHttpContextAccessor accessor) ? ? ? ?{_context = accessor.HttpContext;} ? ? ? ?// GET api/values[HttpGet] ? ? ? ?public ActionResult<IEnumerable<string>> Get(){ ? ? ? ? ? ?return Ok($"獲取到的真實IP:{_context.Connection.RemoteIpAddress}");}

編輯?Startup

? ? ? ?public void ConfigureServices(IServiceCollection services) ? ? ? ?{services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();}

4.測試

(1)將程序部署到服務器

本文略此步

(2)配置 Nginx 反向代理

新建配置文件?realiptest.conf

server { ? ?listen 5002; ? ?access_log ?off; ? ?location / { ? ? ? proxy_pass http://localhost:5000; } }

(3)測試訪問

服務器地址:192.168.157.132

我本機地址:192.168.157.1

那么我本機通過訪問?http://192.168.157.132:5002/api/values?api獲取到的ip地址應該是我本機的,即 192.168.157.1

通過瀏覽器訪問驗證:

可是卻獲取到了 127.0.0.1,這是因為 們的請求到了 Nginx,然后 Nginx 再將我們的請求轉發(fā)到 ASP.NET Core 應用程序,實際上與 ASP.NET Core 應用程序 建立連接的是 Nginx ,所以獲取到了服務器本地 IP (Nginx和程序部署在一臺機子上)。請求流程如下圖:

三.解決問題

修改程序代碼以便顯示更詳細的信息:

ValuesController

? ? ? ?// GET api/values[HttpGet] ? ? ?
? ? ? ?public ActionResult<IEnumerable<string>> Get(){StringBuilder sb=new StringBuilder();sb.AppendLine($"RemoteIpAddress:{_context.Connection.RemoteIpAddress}"); ? ? ? ?
? ? ? ? ? ?if (Request.Headers.ContainsKey("X-Real-IP")){sb.AppendLine($"X-Real-IP:{Request.Headers["X-Real-IP"].ToString()}");} ? ? ? ? ?
? ? ? ? ? ?if (Request.Headers.ContainsKey("X-Forwarded-For")){sb.AppendLine($"X-Forwarded-For:{Request.Headers["X-Forwarded-For"].ToString()}");} ? ? ? ?
? ? ? ? ? ?return Ok(sb.ToString());}

修改反向代理配置:

server { ? ?listen 5002; ? ?access_log ?off; ? ?location / { ? ? ? proxy_set_header ? X-Real-IP ? ? ? ?$remote_addr; ? ? ? proxy_set_header ? Host ? ? ? ? ? ? $host; ? ? ? proxy_set_header ? X-Forwarded-For ?$proxy_add_x_forwarded_for; ? ? ? proxy_pass ? ? ? ? ? ? ? ? ? ? ? ? ?http://localhost:5000;} }

再次訪問:

可以看到X-Real-IP?和?X-Forwarded-For請求頭獲取到了真實IP,我們通過修改 Nginx 配置,讓程序接收到的請求信息攜帶真實IP。Nginx 通過在 X-Real-IP 、X-Forwarded-For 請求頭設置了與它連接的遠程ip

以上解決辦法對于沒有使用CDN是適用的。

四.使用CDN如何解決

我們的請求經(jīng)過一個或者多個cdn結點以后,我們的程序如何獲取真實IP呢,這就要看cdn服務商提供的解決辦法了,一般有兩種:

1.cdn服務商支持設置真實ip到某個指定的請求頭,這樣我們通過這個請求頭就能獲取了 。

2.一般經(jīng)過cdn都會把真實ip經(jīng)過的結點ip信息添加到頭?X-Forwarded-For,我們?nèi)∵@個頭里的第一個ip就是真實ip。

添加 nginx 配置,讓他再次代理 5002 端口(前面添加的代理ASP.NET Core 程序),模擬cdn第二種方案:

server { ? ?listen 5003; ? ?access_log ?off; ? ?location / { ? ? ? proxy_set_header ? X-Real-IP ? ? ? ?$remote_addr; ? ? ? proxy_set_header ? Host ? ? ? ? ? ? $host; ? ? ? proxy_set_header ? X-Forwarded-For ?$proxy_add_x_forwarded_for; ? ? ? proxy_pass ? ? ? ? ? ? ? ? ? ? ? ? ?http://192.168.157.132:5002;} }

我們再次訪問:

可以看到我們的真實ip被放到?X-Forwarded-For?請求頭的第一個IP,X-Real-IP 獲取到的是上一層代理的ip。

X-Forwarded-For 來自百度百科的解釋:X-Forwarded-For 簡稱XFF頭,它代表客戶端,也就是HTTP的請求端真實的IP,只有在通過了HTTP 代理或者負載均衡服務器時才會添加該項。它不是RFC中定義的標準請求頭信息,在squid緩存代理服務器開發(fā)文檔中可以找到該項的詳細介紹。標準格式如下:X-Forwarded-For: client1, proxy1, proxy2。請求流程如下圖:

五.如何在代碼里最小改動

經(jīng)過上面的講解,顯而易見我們在代碼里無法直接通過?RemoteIpAddress?獲取真實ip,那么如果我們在編寫代碼時,很多地方直接采用?RemoteIpAddress獲取真實ip怎么辦,難道需要修改每一處嗎,這里分享一個簡單的解決辦法,就是利用 ASP.NET Core 中間件給 RemoteIpAddress 重新賦值。

編寫 RealIpMiddleware 中間件:

public class RealIpMiddleware{ ? ?private readonly RequestDelegate _next; ? ?public RealIpMiddleware(RequestDelegate next) ? ?{_next = next;} ? ?public Task Invoke(HttpContext context) ? ?{ ? ? ? ?var headers = context.Request.Headers; ? ? ? ?if (headers.ContainsKey("X-Forwarded-For")){context.Connection.RemoteIpAddress=IPAddress.Parse(headers["X-Forwarded-For"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries)[0]);} ? ? ? ?return _next(context);} }

如果是前面提到的cdn的第一種情況,只需判斷cdn服務商提供的特殊請求頭就行了。

在Startup中配置

應放在最靠前的位置,以免有中間件獲取到了未重置的IP地址。

保持前面的模擬cdn第二中情況架構,再次進行測試:

可以看到通過?RemoteIpAddress?獲取到了真實ip。這種解決方案算是比較好的了。

這里提一下 Nginx RealIP Module 是 Nginx 獲取真實ip的一個模塊,有興趣的同學可以自己去研究一下。

六.使用組件 Unicorn.AspNetCore

Unicorn.AspNetCore?里面我有封裝處理ip的中間件。

通過nuget安裝:

Install-Package Unicorn.AspNetCore

然后在 Program 中添加:

開源地址:https://github.com/UCPlan/Unicorn/tree/master/src/Infrastructure/Unicorn.AspNetCore/Middleware/RealIp

原文地址:https://www.cnblogs.com/stulzq/p/9946262.html


.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結

以上是生活随笔為你收集整理的ASP.NET Core 搭配 Nginx 的真实IP问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。