最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Django獲取請求IP的正確方法和最佳實踐

 更新時間:2026年05月26日 16:56:52   作者:detayun  
這篇文章主要為大家詳細介紹了Django獲取客戶端IP的正確方法總結(jié)以及常見錯誤和解決方法,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下

最近在項目中遇到一個詭異的問題:使用域名訪問能獲取到真實IP,但用IP+端口訪問時,獲取到的卻是 127.0.0.1。經(jīng)過一番折騰,終于搞清楚了原因。今天就來總結(jié)一下 Django獲取客戶端IP的正確姿勢!

常見的錯誤寫法

很多同學(包括我自己)一開始會這樣寫:

# ? 錯誤:'IP' 不是Django的標準META key
ip = request.META['IP']  # KeyError!

# ? 錯誤:只用REMOTE_ADDR,代理時會出錯
ip = request.META['REMOTE_ADDR']  # 代理時返回127.0.0.1

踩坑現(xiàn)場

  • 直連服務(wù)器:? 能獲取到真實IP
  • Nginx反向代理:? 返回 127.0.0.1
  • CDN/WAF:? 返回CDN的IP,不是用戶真實IP

Django的META中有哪些IP相關(guān)的Key?

META Key說明直連代理CDN優(yōu)先級
REMOTE_ADDR直連的客戶端IP? 真實IP? 代理IP(127.0.0.1)? 最后一跳IP??
HTTP_X_FORWARDED_FOR代理鏈中的真實IP? 無? 真實IP? 真實IP????
HTTP_X_REAL_IPNginx傳遞的真實IP? 無? 真實IP????
HTTP_CLIENT_IP備用方案? 無????

優(yōu)先級

HTTP_X_FORWARDED_FOR > HTTP_X_REAL_IP > REMOTE_ADDR

最佳實踐:通用獲取IP函數(shù)

方法1:標準寫法(推薦)???

def get_client_ip(request):
    """
    獲取客戶端真實IP(支持直連、代理、CDN)
    
    Args:
        request: Django的HttpRequest對象
    
    Returns:
        str: 客戶端真實IP
    """
    # 1. 優(yōu)先從 HTTP_X_FORWARDED_FOR 獲取(代理傳遞的真實IP)
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        # 可能有多個IP(如:client, proxy1, proxy2),取第一個
        ip = x_forwarded_for.split(',')[0].strip()
    else:
        # 2. 沒有代理,直接用 REMOTE_ADDR
        ip = request.META.get('REMOTE_ADDR', '127.0.0.1')
    
    # 3. 過濾內(nèi)網(wǎng)IP(可選,防止偽造)
    if ip.startswith('127.') or ip.startswith('192.168.'):
        return '0.0.0.0'
    
    return ip

使用示例

def my_view(request):
    ip = get_client_ip(request)
    print(f"客戶端IP: {ip}")  # 輸出:123.45.67.89
    return JsonResponse({'ip': ip})

方法2:更嚴謹?shù)膶懛ǎǚ纻卧欤????

def get_client_ip(request):
    """
    獲取客戶端真實IP(防偽造、支持多層代理)
    """
    # 嘗試多個可能的IP來源(按優(yōu)先級排序)
    ip_keys = [
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_REAL_IP',
        'HTTP_CLIENT_IP',
        'REMOTE_ADDR',
    ]
    
    for key in ip_keys:
        ip = request.META.get(key)
        if ip:
            # HTTP_X_FORWARDED_FOR 可能有多個IP,取第一個
            if key == 'HTTP_X_FORWARDED_FOR':
                ip = ip.split(',')[0].strip()
            
            # 過濾內(nèi)網(wǎng)IP和無效IP
            if ip and not ip.startswith(('127.', '192.168.', '0.')):
                return ip
    
    return '0.0.0.0'

方法3:使用中間件(全局生效)?????

如果你想在所有視圖中都能用 request.client_ip,可以寫個中間件:

# middleware.py
class ClientIPMiddleware:
    """
    中間件:自動在request對象上添加client_ip屬性
    """
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 獲取真實IP
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            request.client_ip = x_forwarded_for.split(',')[0].strip()
        else:
            request.client_ip = request.META.get('REMOTE_ADDR', '127.0.0.1')
        
        response = self.get_response(request)
        return response

配置中間件settings.py):

MIDDLEWARE = [
    # ... 其他中間件
    'myapp.middleware.ClientIPMiddleware',  # ? 添加這行
]

使用

def my_view(request):
    ip = request.client_ip  # ? 直接用,超方便!
    print(f"客戶端IP: {ip}")
    return JsonResponse({'ip': ip})

Nginx配置(最優(yōu)雅的方案)?????

如果你用Nginx做反向代理,在Nginx層傳遞真實IP是最優(yōu)解

server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
        # ??? 關(guān)鍵:傳遞真實IP ???
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

然后Django中直接用:

# ? 現(xiàn)在REMOTE_ADDR就是真實IP了
ip = request.META.get('REMOTE_ADDR')

不同場景對比

場景直連Nginx代理CDN/WAF推薦方法
REMOTE_ADDR? 真實IP? 127.0.0.1? CDN IP? 不推薦
HTTP_X_FORWARDED_FOR? 無? 真實IP? 真實IP????
中間件 request.client_ip????????
Nginx配置????????

常見坑點

坑1:HTTP_X_FORWARDED_FOR可以偽造!

# 惡意請求(偽造IP)
curl -H "X-Forwarded-For: 8.8.8.8" http://your-server.com

解決方案

  • 只信任自己的Nginx/CDN(配置白名單)
  • 過濾內(nèi)網(wǎng)IP(127.*, 192.168.*
  • 使用 HTTP_X_REAL_IP(Nginx專屬,難以偽造)

坑2:多層代理時,HTTP_X_FORWARDED_FOR有多個IP

用戶 → 代理1 → 代理2 → 你的服務(wù)器

HTTP_X_FORWARDED_FOR = "用戶IP, 代理1IP, 代理2IP"

解決方案

# 取第一個(最左邊的是真實IP)
ip = request.META.get('HTTP_X_FORWARDED_FOR').split(',')[0].strip()

坑3:IPv6的IP獲取

# IPv6地址示例:2001:0db8:85a3::8a2e:0370:7334
# 同樣適用上述方法
ip = get_client_ip(request)  # 支持IPv4和IPv6

完整工具類(直接復制用)

# utils.py
class IPUtils:
    @staticmethod
    def get_client_ip(request):
        """獲取客戶端真實IP(防偽造、支持代理)"""
        for key in ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'REMOTE_ADDR']:
            ip = request.META.get(key)
            if ip:
                if key == 'HTTP_X_FORWARDED_FOR':
                    ip = ip.split(',')[0].strip()
                if ip and not ip.startswith(('127.', '192.168.', '0.')):
                    return ip
        return '0.0.0.0'

# 使用
from myapp.utils import IPUtils
ip = IPUtils.get_client_ip(request)

總結(jié)

方法代碼推薦度適用場景
? request.META['IP']錯誤?別用!
? get_client_ip()上面的函數(shù)?????通用推薦
? 中間件request.client_ip?????全局使用
? Nginx配置proxy_set_header?????有Nginx時

最終推薦

# ? 最簡單:復制這個函數(shù)就夠了
def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        return x_forwarded_for.split(',')[0].strip()
    return request.META.get('REMOTE_ADDR', '127.0.0.1')

# 使用
ip = get_client_ip(request)

一句話總結(jié):別用 request.META['IP'],用 HTTP_X_FORWARDED_FORREMOTE_ADDR! ??

提示:如果你的服務(wù)在CDN后面(如Cloudflare),記得在CDN控制臺開啟"傳遞真實IP"功能,否則 HTTP_X_FORWARDED_FOR 也會是CDN的IP哦!

到此這篇關(guān)于Django獲取請求IP的正確方法和最佳實踐的文章就介紹到這了,更多相關(guān)Django獲取請求IP內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

和平县| 和平县| 兰考县| 安多县| 九江县| 连城县| 商城县| 崇左市| 开化县| 女性| 黄石市| 庆云县| 五河县| 丽水市| 永善县| 肇源县| 湟中县| 元阳县| 长泰县| 遂宁市| 改则县| 怀柔区| 德化县| 峡江县| 广水市| 北流市| 仪陇县| 新化县| 夏邑县| 汨罗市| 山东省| 锡林浩特市| 麻栗坡县| 蓬安县| 平果县| 漳州市| 营口市| 玉田县| 双峰县| 寻乌县| 常熟市|