Nuxt3:如何在每次请求时向客户端提供服务端计算的变量
实现服务端判断客户端IP并传递
shouldShowSettings变量到客户端 核心逻辑
每次收到客户端请求时,服务端先提取真实客户端IP,判断是否属于内部IP段,生成shouldShowSettings布尔变量,再通过模板渲染注入、全局JS变量或API接口三种方式传递给客户端,供菜单组件做显示/隐藏判断。
常见服务端框架实现示例
Node.js + Express
1. 全局中间件计算变量
先实现IP判断工具函数,再通过全局中间件处理所有请求:
const express = require('express'); const app = express(); // 判定内部IP的正则(覆盖A/B/C类私有IP段) const isInternalIp = (ip) => /^(10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)/.test(ip); // 全局中间件:处理IP判断并挂载变量 app.use((req, res, next) => { // 优先取反向代理传递的真实IP,否则用内置req.ip const clientIp = req.headers['x-forwarded-for']?.split(',')[0].trim() || req.ip; // 把变量挂载到res.locals,供模板直接使用 res.locals.shouldShowSettings = isInternalIp(clientIp); next(); }); // 开启反向代理信任(如果部署在Nginx等代理后,必须加这行) app.set('trust proxy', true);
2. 传递给客户端的两种方式
- 服务端模板渲染(比如EJS):
<!-- index.ejs --> <% if (shouldShowSettings) { %> <nav class="settings-menu"> <a href="/settings">系统设置</a> </nav> <% } %>
- SPA场景:通过API接口返回:
// 新增接口 app.get('/api/visibility', (req, res) => { res.json({ shouldShowSettings: res.locals.shouldShowSettings }); }); // 客户端初始化时调用 async function loadSettingsVisibility() { const res = await fetch('/api/visibility'); const { shouldShowSettings } = await res.json(); // 挂载到全局或状态管理工具中 window.shouldShowSettings = shouldShowSettings; // 控制菜单显示 document.getElementById('settings-menu').style.display = shouldShowSettings ? 'block' : 'none'; } loadSettingsVisibility();
PHP
1. 计算变量并传递
<?php // 内部IP判断函数 function isInternalIp($ip) { return preg_match('/^(10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)/', $ip); } // 获取真实客户端IP $clientIp = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR']; $shouldShowSettings = isInternalIp($clientIp); ?>
2. 模板中直接使用或注入全局JS
<!-- PHP模板直接渲染 --> <?php if ($shouldShowSettings): ?> <div class="settings-menu"> <a href="/settings">系统设置</a> </div> <?php endif; ?> <!-- 注入全局JS供前端组件调用 --> <script> window.shouldShowSettings = <?= json_encode($shouldShowSettings) ?>; </script>
Python Django
1. 自定义中间件处理IP判断
# myapp/middlewares.py import re class SettingsVisibilityMiddleware: def __init__(self, get_response): self.get_response = get_response self.internal_ip_pattern = re.compile(r'^(10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)') def __call__(self, request): # 提取真实客户端IP client_ip = request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR')).split(',')[0].strip() # 将判断结果挂载到request对象 request.should_show_settings = self.internal_ip_pattern.match(client_ip) is not None response = self.get_response(request) return response
2. 上下文处理器传递到模板
# myapp/context_processors.py def settings_visibility(request): return {'should_show_settings': getattr(request, 'should_show_settings', False)}
然后在settings.py中注册中间件和上下文处理器:
MIDDLEWARE = [ # ...其他默认中间件 'myapp.middlewares.SettingsVisibilityMiddleware', ] TEMPLATES = [ { # ...其他配置 'OPTIONS': { 'context_processors': [ # ...默认处理器 'myapp.context_processors.settings_visibility', ], }, }, ]
3. 模板中使用变量
{% if should_show_settings %} <nav class="settings-menu"> <a href="{% url 'settings' %}">系统设置</a> </nav> {% endif %}
关键注意事项
- 反向代理场景:必须在服务端配置信任代理IP(比如Express的
trust proxy、Django的USE_X_FORWARDED_HOST),否则可能获取到代理IP而非真实客户端IP,同时防止X-Forwarded-For头被伪造。 - IP段扩展:如果你的内部IP段不在标准私有IP范围内,需要修改正则表达式或判断逻辑。
- 安全提示:视觉隐藏仅为优化用户体验,不能替代服务端的路由/API权限校验,已有的服务端保护逻辑需保留。
内容的提问来源于stack exchange,提问作者Michael Ochs
相关产品推荐
相关产品推荐

