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

Django獲取請(qǐng)求IP的正確方法和最佳實(shí)踐

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

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

常見的錯(cuò)誤寫法

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

# ? 錯(cuò)誤:'IP' 不是Django的標(biāo)準(zhǔn)META key
ip = request.META['IP']  # KeyError!

# ? 錯(cuò)誤:只用REMOTE_ADDR,代理時(shí)會(huì)出錯(cuò)
ip = request.META['REMOTE_ADDR']  # 代理時(shí)返回127.0.0.1

踩坑現(xiàn)場(chǎng)

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

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

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

優(yōu)先級(jí)

HTTP_X_FORWARDED_FOR > HTTP_X_REAL_IP > REMOTE_ADDR

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

方法1:標(biāo)準(zhǔn)寫法(推薦)???

def get_client_ip(request):
    """
    獲取客戶端真實(shí)IP(支持直連、代理、CDN)
    
    Args:
        request: Django的HttpRequest對(duì)象
    
    Returns:
        str: 客戶端真實(shí)IP
    """
    # 1. 優(yōu)先從 HTTP_X_FORWARDED_FOR 獲?。ù韨鬟f的真實(shí)IP)
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        # 可能有多個(gè)IP(如:client, proxy1, proxy2),取第一個(gè)
        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:更嚴(yán)謹(jǐn)?shù)膶懛ǎǚ纻卧欤????

def get_client_ip(request):
    """
    獲取客戶端真實(shí)IP(防偽造、支持多層代理)
    """
    # 嘗試多個(gè)可能的IP來源(按優(yōu)先級(jí)排序)
    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 可能有多個(gè)IP,取第一個(gè)
            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,可以寫個(gè)中間件:

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

    def __call__(self, request):
        # 獲取真實(shí)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層傳遞真實(shí)IP是最優(yōu)解

server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
        # ??? 關(guān)鍵:傳遞真實(shí)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就是真實(shí)IP了
ip = request.META.get('REMOTE_ADDR')

不同場(chǎng)景對(duì)比

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

常見坑點(diǎn)

坑1:HTTP_X_FORWARDED_FOR可以偽造!

# 惡意請(qǐng)求(偽造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:多層代理時(shí),HTTP_X_FORWARDED_FOR有多個(gè)IP

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

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

解決方案

# 取第一個(gè)(最左邊的是真實(shí)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

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

# utils.py
class IPUtils:
    @staticmethod
    def get_client_ip(request):
        """獲取客戶端真實(shí)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é)

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

最終推薦

# ? 最簡(jiǎn)單:復(fù)制這個(gè)函數(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控制臺(tái)開啟"傳遞真實(shí)IP"功能,否則 HTTP_X_FORWARDED_FOR 也會(huì)是CDN的IP哦!

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

相關(guān)文章

最新評(píng)論

永宁县| 洪雅县| 长乐市| 云林县| 呼图壁县| 榕江县| 麦盖提县| 闵行区| 江山市| 平度市| 武定县| 彭州市| 永春县| 淳安县| 闵行区| 星座| 正定县| 七台河市| 江西省| 桦南县| 两当县| 天峨县| 垣曲县| 北海市| 卢龙县| 金昌市| 兴化市| 鄂尔多斯市| 林州市| 和田县| 象山县| 舒城县| 分宜县| 宽甸| 静乐县| 南康市| 赣榆县| 望江县| 南阳市| 宁津县| 温宿县|