mirror of
https://github.com/insistence/RuoYi-Vue3-FastAPI.git
synced 2026-10-10 03:14:14 +00:00
61 lines
2.0 KiB
Python
61 lines
2.0 KiB
Python
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()}
|