<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:wfw="http://wellformedweb.org/CommentAPI/">
<channel>
<title>解说文案 - IP查询</title>
<link>https://xwean.com/tag/IP%E6%9F%A5%E8%AF%A2/</link>
<atom:link href="https://xwean.com/feed/tag/IP%E6%9F%A5%E8%AF%A2/" rel="self" type="application/rss+xml" />
<language>zh-CN</language>
<description></description>
<lastBuildDate>Sat, 16 Mar 2024 18:12:25 +0800</lastBuildDate>
<pubDate>Sat, 16 Mar 2024 18:12:25 +0800</pubDate>
<item>
<title>简单的IP查询页面制作</title>
<link>https://xwean.com/1959.html</link>
<guid>https://xwean.com/1959.html</guid>
<pubDate>Sat, 16 Mar 2024 18:12:25 +0800</pubDate>
<dc:creator>hhs</dc:creator>
<description><![CDATA[简单的IP查询页面制作如图会根据受访者的IP定位查询天气但时间来说 就是自己电脑的时间本来想做时区的，但发现没那个必要  好歹有个东西能辨别一下真伪需要用的2个api key一个是https:/...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h3>简单的IP查询页面制作</h3><p>如图</p><p><img src="http://pic2.xwean.com/typora1/2023/202403161739499.png" alt="image-20240316173951473" title="image-20240316173951473"></p><p>会根据受访者的IP定位查询天气</p><p>但时间来说 就是自己电脑的时间</p><p>本来想做时区的，但发现没那个必要  好歹有个东西能辨别一下真伪</p><p>需要用的2个api key</p><p>一个是</p><p><a href="https://ipinfo.io/">https://ipinfo.io/</a></p><p>↑ 查询IP地址的</p><p>每个月5万次查询，超过就罢工  免费的</p><p>花钱的</p><p><img src="http://pic2.xwean.com/typora1/2023/202403161743976.png" alt="image-20240316174311934" title="image-20240316174311934"></p><p>所以还是省点吧</p><p>o(╥﹏╥)o</p><p><strong>另一个是天气的api</strong></p><p><a href="https://link.juejin.cn/?target=https%3A%2F%2Fhome.openweathermap.org%2F">home.openweathermap.org/</a></p><p><img src="http://pic2.xwean.com/typora1/2023/202403161745318.png" alt="image-20240316174533251" title="image-20240316174533251"></p><p>直接注册就行</p><p>当2个api弄好之后 开始部署</p><h4>服务器 用的是 ubantu</h4><p>用到的 前端  后端js  最后的nginx配置</p><h5>首先前端好弄</h5><p><strong>↓</strong></p><p><strong>拿来直接就可以用</strong></p><pre><code class="lang-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;zh-CN&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;看看天气咋样&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: &#039;Arial&#039;, sans-serif;
            background-color: #f0f0f0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            flex-direction: column;
        }

        .container {
            background-color: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            width: 300px;
            text-align: center;
            margin-bottom: 20px; /* 与底部文字保持距离 */
        }

        .info-box {
            background-color: #E9ECEF;
            padding: 10px;
            margin: 10px 0;
            border-radius: 5px;
        }

        .footer {
            color: black; /* 设置底部文字颜色 */
            font-size: 12px; /* 设置底部文字大小 */
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class=&quot;container&quot;&gt;
        &lt;h1&gt;我的天气！&lt;/h1&gt;
        &lt;div id=&quot;ip&quot; class=&quot;info-box&quot;&gt;IP地址：加载中...&lt;/div&gt;
        &lt;div id=&quot;location&quot; class=&quot;info-box&quot;&gt;位置：加载中...&lt;/div&gt;
        &lt;div id=&quot;weather&quot; class=&quot;info-box&quot;&gt;天气：加载中...&lt;/div&gt;
        &lt;div id=&quot;time&quot; class=&quot;info-box&quot;&gt;当前时间：加载中...&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;footer&quot;&gt;
        私人网盘正在开发中....
    &lt;/div&gt;
    &lt;script&gt;
        // 获取IP和位置信息
        fetch(&#039;/get-ip-info&#039;)
            .then(response =&gt; response.json())
            .then(data =&gt; {
                document.getElementById(&#039;ip&#039;).textContent = `IP地址：${data.ip}`;
                document.getElementById(&#039;location&#039;).textContent = `位置：${data.country} - ${data.city} - ${data.region}`;
                
                // 使用获取到的位置信息请求天气数据
                return fetch(`/get-weather?city=${data.city}`);
            })
            .then(response =&gt; response.json())
            .then(data =&gt; {
                document.getElementById(&#039;weather&#039;).textContent = `天气：${data.weather[0].main}, 温度：${data.main.temp}°C`;
            })
            .catch(error =&gt; console.error(&#039;获取信息失败&#039;, error));

        // 显示当前时间
        document.getElementById(&#039;time&#039;).textContent = `当前时间：${new Date().toLocaleTimeString()}`;
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>直接复制黏贴上去就行，方便的很。</p><p>当然，这前端大神也可以自己改一改</p><p>随后就到了后端！</p><p>其实最开始的时候，直接把key 打进前端。但，可一个F12 基本上就曝光了</p><p>比如这样</p><pre><code class="lang-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;当前天气&lt;/title&gt;
    &lt;script&gt;
        function fetchWeather() {
            const apiKey = &#039;YOUR_API_KEY_HERE&#039;; // 替换为您的API密钥
            const city = &#039;Beijing&#039;; // 您想查询的城市
            const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&amp;appid=${apiKey}&amp;units=metric`;

            fetch(url)
                .then(response =&gt; response.json())
                .then(data =&gt; {
                    document.getElementById(&#039;weather&#039;).innerText = `当前温度: ${data.main.temp}°C`;
                })
                .catch(error =&gt; console.error(&#039;Error:&#039;, error));
        }
    &lt;/script&gt;
&lt;/head&gt;
&lt;body onload=&quot;fetchWeather();&quot;&gt;
    &lt;h1&gt;当前天气&lt;/h1&gt;
    &lt;p id=&quot;weather&quot;&gt;加载中...&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>Or</p><pre><code class="lang-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;我的天气应用&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: &#039;Arial&#039;, sans-serif;
            background-color: #f0f0f0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }

        .container {
            background-color: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            width: 300px;
            text-align: center;
        }

        h1 {
            color: #007BFF;
            margin-bottom: 20px;
        }

        .info-box {
            background-color: #E9ECEF;
            padding: 10px;
            margin: 10px 0;
            border-radius: 5px;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class=&quot;container&quot;&gt;
        &lt;h1&gt;我的天气应用&lt;/h1&gt;
        &lt;div id=&quot;ip&quot; class=&quot;info-box&quot;&gt;IP地址：加载中...&lt;/div&gt;
        &lt;div id=&quot;location&quot; class=&quot;info-box&quot;&gt;位置：加载中...&lt;/div&gt;
        &lt;div id=&quot;weather&quot; class=&quot;info-box&quot;&gt;天气：加载中...&lt;/div&gt;
    &lt;/div&gt;
    &lt;script&gt;
        // 此处需要您填写自己的API密钥
        const ipinfoToken = &#039;YOUR_IPINFO_TOKEN&#039;; // 替换为您的IPinfo API令牌
        const openWeatherMapApiKey = &#039;YOUR_OPENWEATHERMAP_API_KEY&#039;; // 替换为您的OpenWeatherMap API密钥

        fetch(`https://ipinfo.io/json?token=${ipinfoToken}`)
            .then(response =&gt; response.json())
            .then(data =&gt; {
                const ip = data.ip;
                const location = `${data.city}, ${data.region}, ${data.country}`;
                document.getElementById(&#039;ip&#039;).textContent = `IP地址：${ip}`;
                document.getElementById(&#039;location&#039;).textContent = `位置：${location}`;

                return fetch(`https://api.openweathermap.org/data/2.5/weather?q=${data.city}&amp;appid=${openWeatherMapApiKey}&amp;units=metric`);
            })
            .then(response =&gt; response.json())
            .then(data =&gt; {
                const weather = `${data.weather[0].main}, 温度：${data.main.temp}°C`;
                document.getElementById(&#039;weather&#039;).textContent = `天气：${weather}`;
            })
            .catch(error =&gt; console.error(&#039;Error:&#039;, error));
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>最后还是升级了一下</p><p>大概是这个思路</p><pre><code class="lang-html">const express = require(&#039;express&#039;);
const fetch = require(&#039;node-fetch&#039;);
const app = express();
const PORT = 3000;

const IPINFO_TOKEN = process.env.IPINFO_TOKEN; // 假设您已经将 API 密钥保存在环境变量中
const OPENWEATHERMAP_API_KEY = process.env.OPENWEATHERMAP_API_KEY;

app.get(&#039;/weather&#039;, async (req, res) =&gt; {
    // 获取客户端 IP 地址
    const clientIp = req.ip;

    // 使用 IP 地址获取地理位置
    const locationResponse = await fetch(`https://ipinfo.io/${clientIp}/json?token=${IPINFO_TOKEN}`);
    const locationData = await locationResponse.json();
    const city = locationData.city;

    // 使用地理位置获取天气信息
    const weatherResponse = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&amp;appid=${OPENWEATHERMAP_API_KEY}&amp;units=metric`);
    const weatherData = await weatherResponse.json();

    // 将天气信息返回给前端
    res.json(weatherData);
});

app.listen(PORT, () =&gt; {
    console.log(`Server is running on http://localhost:${PORT}`);
});
</code></pre><h5>安装Node.js</h5><pre><code>cd ~
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -</code></pre><pre><code>sudo apt-get install -y nodejs</code></pre><pre><code>cd /path/to/your/project
npm install</code></pre><pre><code>node app.js</code></pre><p>安装的时候可能找不到npm</p><pre><code>which npm</code></pre><pre><code>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash</code></pre><pre><code>nvm install node  # 安装最新版本的Node.js和npm</code></pre><p>安装</p><pre><code>npm install dotenv</code></pre><p>这个是储存key的</p><p>在 /var/www/html/app中 新建一个 <code>.env</code> 文件</p><pre><code>IPINFO_TOKEN=XXXXXXXXX
OPENWEATHERMAP_API_KEY=XXXXXXXX</code></pre><p>将 XXX 替换成自己的key</p><p>然后dotenv加载.env文件</p><pre><code>require(&#039;dotenv&#039;).config();

const ipinfoToken = process.env.IPINFO_TOKEN;
const openWeatherMapApiKey = process.env.OPENWEATHERMAP_API_KEY;</code></pre><p><strong>如果出现问题，应该是没有正确安装</strong></p><p>重新安装</p><pre><code>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash</code></pre><p>初始化代码：</p><pre><code>export NVM_DIR=&quot;$HOME/.nvm&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;&amp; \. &quot;$NVM_DIR/nvm.sh&quot;  # This loads nvm
[ -s &quot;$NVM_DIR/bash_completion&quot; ] &amp;&amp; \. &quot;$NVM_DIR/bash_completion&quot;  # This loads nvm bash_completion</code></pre><p>都完事了，就在<code> /var/www/html/app</code> 创建 <code>index.js</code></p><p>同时也要创建 <code>.env</code></p><p>这个 .env 的 文件夹中 就2行 一个IP的key 一个天气的key</p><pre><code>IPINFO_TOKEN=XXXXXXXX
OPENWEATHERMAP_API_KEY=XXXXXX</code></pre><p>完整的后端代码如下</p><pre><code class="lang-js">require(&#039;dotenv&#039;).config(); // 加载环境变量

const express = require(&#039;express&#039;);
const fetch = require(&#039;node-fetch&#039;);
const morgan = require(&#039;morgan&#039;);
const fs = require(&#039;fs&#039;);
const path = require(&#039;path&#039;);

const app = express();
const PORT = process.env.PORT || 3000;

// 创建一个写入流，并将日志写入到指定文件中
const accessLogStream = fs.createWriteStream(path.join(__dirname, &#039;access.log&#039;), { flags: &#039;a&#039; });

// 设置morgan日志记录中间件，将日志输出到文件中
app.use(morgan(&#039;combined&#039;, { stream: accessLogStream }));

// 获取IP地址信息的路由
app.get(&#039;/get-ip-info&#039;, async (req, res) =&gt; {
    const ipinfoToken = process.env.IPINFO_TOKEN;
    // 获取请求者的IP地址
    const visitorIp = req.headers[&#039;x-forwarded-for&#039;]?.split(&#039;,&#039;).shift() || req.connection.remoteAddress;

    if (!visitorIp) {
        res.status(500).json({ error: &#039;无法获取位置IP&#039; });
        return;
    }

    try {
        // 调用IPinfo API获取访问者的IP地址信息
        const ipinfoResponse = await fetch(`https://ipinfo.io/${visitorIp}?token=${ipinfoToken}`);
        const ipinfoData = await ipinfoResponse.json();

        // 如果返回的数据不包含IP信息，则停止并返回错误
        if (!ipinfoData || !ipinfoData.ip) {
            res.status(500).json({ error: &#039;无法获取位置IP&#039; });
            return;
        }

        res.json(ipinfoData); // 将访问者的IP地址信息发送给前端
    } catch (error) {
        console.error(&#039;Error fetching IP info:&#039;, error);
        res.status(500).json({ error: &#039;Server Error&#039; });
    }
});

// 获取天气信息的路由
app.get(&#039;/get-weather&#039;, async (req, res) =&gt; {
    const openWeatherMapApiKey = process.env.OPENWEATHERMAP_API_KEY;
    const city = req.query.city; // 从查询参数中获取城市名称

    if (!city) {
        res.status(400).json({ error: &#039;城市名称是必需的&#039; });
        return;
    }

    try {
        // 根据城市名称获取天气信息
        const weatherResponse = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&amp;appid=${openWeatherMapApiKey}&amp;units=metric`);
        const weatherData = await weatherResponse.json();

        // 如果API返回了错误
        if (weatherData.cod != 200) {
            res.status(weatherData.cod).json({ error: weatherData.message });
            return;
        }

        res.json(weatherData); // 将天气信息发送给前端
    } catch (error) {
        console.error(&#039;Error fetching weather data:&#039;, error);
        res.status(500).json({ error: &#039;Server Error&#039; });
    }
});

app.listen(PORT, () =&gt; {
    console.log(`Server running on port ${PORT}`);
});
</code></pre><p>发现漏洞</p><pre><code>npm audit fix</code></pre><p>没事可以弄一个日志 看看出啥问题了</p><pre><code>morgan</code></pre><p>最后一步 修改NGINX</p><p>因为之前已经做了其他事情，只能重新硬改一下</p><pre><code class="lang-conf">user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 1024;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    gzip on;

    # HTTPS Server
    server {
        listen 443 ssl;
        
        server_name baidu.com;  # 替换成你的域名
        ssl_certificate       /etc/???/server.crt;  # 证书位置
        ssl_certificate_key   /etc/???/server.key; # 私钥位置
        
        ssl_session_timeout 1d;
        ssl_session_cache shared:MozSSL:10m;
        ssl_session_tickets off;
        ssl_protocols    TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers off;

        location / {
            root   /var/www/html;
            index  index.html index.htm;
        }

       

        # Node.js应用的反向代理配置
        location /get-ip-info {
            proxy_pass http://localhost:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection &#039;upgrade&#039;;
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
        }

        location /get-weather {
            proxy_pass http://localhost:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection &#039;upgrade&#039;;
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }

    # HTTP Server (用于SSL证书验证和HTTP到HTTPS的重定向)
    server {
        listen 80;
        location /.well-known/ {
            root /var/www/html;
        }
        location / {
            return 301 https://$host$request_uri;
        }
    }
}</code></pre><p>完事了</p><p>版本不出意外的话 不会再继续更新</p><p>代码有点垃的感觉</p><p>没有做docker 也没做一键安装脚本</p><p>建议用pm2 做一下进程管理 </p><p>有啥问题评论区吧。。</p><p><strong>下课</strong></p>
]]></content:encoded>
<slash:comments>1</slash:comments>
<comments>https://xwean.com/1959.html#comments</comments>
<wfw:commentRss>https://xwean.com/feed/tag/IP%E6%9F%A5%E8%AF%A2/</wfw:commentRss>
</item>
</channel>
</rss>