You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Streamlit部署的Python Web应用中获取用户真实IP地址

解决Streamlit Sharing部署后获取用户真实IP的问题

嘿,我之前在Streamlit Sharing上部署应用时也碰到过一模一样的坑!当时百思不得其解,后来才搞明白为啥会这样:

问题根源

本地测试时,你的代码在自己的设备上运行,调用https://ipapi.co/json/接口时,接口会识别发起请求的设备IP(也就是你的公网IP),所以返回正确结果。但部署到Streamlit Sharing后,你的代码是在Streamlit的云端服务器上执行的——此时调用ipapi接口的是Streamlit的服务器,接口自然会返回服务器的IP,而不是使用应用的用户的真实IP。

解决方案:从请求头提取用户真实IP

Streamlit在新版本中提供了访问用户请求上下文的能力,我们可以通过请求头里的代理字段拿到用户的真实IP(因为Streamlit Sharing用了反向代理,用户的真实IP会被放在特定的请求头中)。具体步骤如下:

  1. 获取用户真实IP:从请求头的X-Forwarded-For字段提取,这个字段是反向代理服务器添加的,记录了原始请求的IP地址(如果经过多层代理,会是逗号分隔的多个IP,取第一个即可)。如果这个字段不存在,再 fallback 到X-Real-IP或请求的远程地址。
  2. 将用户IP传入ipapi接口:不再让接口自动识别IP,而是主动把用户的真实IP拼接到接口URL中,调用https://ipapi.co/{user_ip}/json/

完整代码示例

import streamlit as st
import requests

def get_user_real_ip():
    # 获取当前请求的上下文对象(需要Streamlit >=1.21.0)
    request = st.context.request
    
    # 优先从X-Forwarded-For提取真实IP
    forwarded_for = request.headers.get("X-Forwarded-For")
    if forwarded_for:
        # 处理可能的多IP情况(比如经过多层代理),取第一个
        user_ip = forwarded_for.split(",")[0].strip()
    else:
        # 备选方案:从X-Real-IP或远程地址获取
        user_ip = request.headers.get("X-Real-IP", request.remote_addr)
    return user_ip

def fetch_ip_details(user_ip):
    # 调用ipapi接口,传入用户真实IP
    api_url = f"https://ipapi.co/{user_ip}/json/"
    try:
        response = requests.get(api_url)
        response.raise_for_status()  # 抛出HTTP错误
        return response.json()
    except requests.exceptions.RequestException as e:
        return {"error": f"无法获取IP信息:{str(e)}"}

# 应用主逻辑
st.title("用户IP信息追踪")

user_ip = get_user_real_ip()
st.success(f"你的真实IP地址:{user_ip}")

ip_details = fetch_ip_details(user_ip)
if "error" not in ip_details:
    st.subheader("IP详细信息")
    st.markdown(f"""
    - **国家**: {ip_details.get("country_name", "未知")}
    - **地区**: {ip_details.get("region", "未知")}
    - **城市**: {ip_details.get("city", "未知")}
    - **运营商**: {ip_details.get("org", "未知")}
    """)
else:
    st.error(ip_details["error"])

注意事项

  • 确保你的Streamlit版本 >=1.21.0,因为st.context.request是在这个版本之后引入的。可以在requirements.txt里指定streamlit>=1.21.0
  • X-Forwarded-For字段在Streamlit Sharing环境下是可信的,平台会正确传递用户的真实IP,不用担心伪造问题。

内容的提问来源于stack exchange,提问作者SUBHABRATA NATH

火山引擎 最新活动