ShiErFeng/shierfeng-fastapi-backend/utils/client_ip_util.py
2026-07-24 09:43:10 +08:00

61 lines
2.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import Request
from config.env import AppConfig
class ClientIPUtil:
"""
客户端IP提取工具
"""
@classmethod
def get_client_ip(cls, request: Request) -> str:
"""
获取客户端真实IP
仅当请求来源命中可信代理列表且可信代理跳数大于0时才会解析
X-Forwarded-For / X-Real-IP 请求头;否则回退到直接连接来源地址。
:param request: 当前请求对象
:return: 客户端IP
"""
remote_addr = request.client.host if request.client else 'unknown'
if AppConfig.app_trusted_proxy_hops <= 0:
return remote_addr
if not cls._should_trust_proxy_headers(remote_addr):
return remote_addr
forwarded_for = request.headers.get('X-Forwarded-For', '')
if forwarded_for:
forwarded_chain = [item.strip() for item in forwarded_for.split(',') if item.strip()]
if forwarded_chain:
if len(forwarded_chain) > AppConfig.app_trusted_proxy_hops:
return forwarded_chain[-(AppConfig.app_trusted_proxy_hops + 1)]
return forwarded_chain[0]
real_ip = request.headers.get('X-Real-IP', '').strip()
if real_ip:
return real_ip
return remote_addr
@classmethod
def _should_trust_proxy_headers(cls, remote_addr: str) -> bool:
"""
判断当前连接来源是否属于可信代理
:param remote_addr: 与应用直接建立连接的来源IP
:return: 是否信任代理头
"""
trusted_proxy_ips = cls._get_trusted_proxy_ips()
return '*' in trusted_proxy_ips or remote_addr in trusted_proxy_ips
@classmethod
def _get_trusted_proxy_ips(cls) -> set[str]:
"""
获取可信代理IP集合
:return: 可信代理IP集合
"""
return {item.strip() for item in AppConfig.app_trusted_proxy_ips.split(',') if item.strip()}