系统地址配置指引
概览
目标
- 在安全隔离场景下,实现内网管理端发布问卷时显示外网答题链接和二维码
- 通过系统地址配置,确保答题页面通过外网域名访问,管理页面通过内网访问
核心原理
- 问卷发布页面默认读取当前页面的
origin
生成答题链接 - 配置系统地址后,优先使用配置的外网域名生成答题链接
- 通过 Nginx 配置实现内外网访问隔离
配置位置
-
基 础设置 → 配置管理 → 界面配置 → 系统地址配置
使用场景
- 内网访问管理页面,外网访问答题页面
- 确保答题链接和二维码显示外网地址,便于外部用户访问
快速配置
快速配置目标
- 快速完成系统地址配置,实现内外网访问隔离
步骤
-
配置系统地址
- 登录管理后台(通过内网域名:
https://admin.survey.example.com
) - 进入"基础设置 → 配置管理 → 界面配置 → 系统地址配置"
- 在"系统地址"字段填入外网域名:
https://survey.example.com
- 保存配置
- 登录管理后台(通过内网域名:
-
验证配置生效
- 进入任意问卷的"问卷设置 → 发布"页面
- 检查答题链接和二维码是否显示外网域名
- 如仍显示内网域名,请清理浏览器缓存或重新发布
验证结果
- 答题链接前缀显示为配置的外网域名
- 外网域名可正常访问答题页面
- 管理后台仍通过内网访问
详细配置步骤
详细配置目标
- 完成系统地址配置并同步调整外网 Nginx 配置,实现安全隔离
前置条件
- 已完成外网域名 DNS 解析
- 具备外网 Nginx 配置文件编辑权限
配置步骤
-
配置系统地址
- 登录管理后台(通过内网域名:
https://admin.survey.example.com
) - 进入"基础设置 → 配置管理 → 界面配置 → 系统地址配置"
- 在"系统地址"字段填入外网域名:
https://survey.example.com
- 保存配置
- 登录管理后台(通过内网域名:
-
验证发布页展示
- 打开任意问卷的发布页面
- 确认答题链接和二维码显示外网域名
- 如仍显示内网域名,清理浏览器缓存后重新 发布
-
配置外网 Nginx
- 根据前端路由配置,只允许答题相关页面通过外网访问
- 禁止管理后台接口外网访问
Nginx 配置
Nginx 配置目标
- 根据前端路由配置,生成对应的 Nginx 配置,实现安全隔离
配置说明
- 双域名架构:外网域名用于答题页面,内网域名用于管理后台
- 安全隔离:外网只允许答题相关页面访问,内网提供完整管理功能
- 严格拒绝:外网非目标路径直接拒绝访问(403 Forbidden)
- 访问控制:通过不同的 server_name 实现严格的访问控制
- SSL 加密:两个域名都支持 HTTPS 访问
- 静态资源优化:保持原有的缓存策略
完整配置示例
# 外网访问配置 - 只允许答题相关页面
server {
listen 443 ssl;
server_name survey.example.com; # 外网域名
root /var/www/surveyking;
# SSL 配置
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# 只允许答题相关页面访问
location ~ ^/(e|s|t|redeem)/ {
try_files $uri $uri/ /index.html;
}
# 处理根路径重定向到首页
location = / {
try_files $uri $uri/ /index.html;
}
# 单独处理 HTML 文件的缓存策略
location ~* \.(html|htm)$ {
# 禁用缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
# 可选:添加版本标识
add_header X-Version $date_gmt;
}
# 静态资源可以长期缓存(因为文件名带 hash)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 二维码代理
location /captcha {
# 修改为实际后端端口
proxy_pass http://localhost:1991/captcha;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 30m;
proxy_http_version 1.1;
proxy_set_header Connection close;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_send_timeout 1800;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
# 允许答题相关接口外网访问
location /admin-api/survey/ {
# 修改为实际后端端口
proxy_pass http://localhost:1991/admin-api/survey/;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 30m;
proxy_http_version 1.1;
proxy_set_header Connection close;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_send_timeout 1800;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
# 允许抽奖相关接口外网访问
location /admin-api/lottery/ {
# 修改为实际后端端口
proxy_pass http://localhost:1991/admin-api/lottery/;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 30m;
proxy_http_version 1.1;
proxy_set_header Connection close;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_send_timeout 1800;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
# 允许认证接口外网访问
location /system/auth/ {
# 修改为实际后端端口
proxy_pass http://localhost:1991/system/auth/;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 30m;
proxy_http_version 1.1;
proxy_set_header Connection close;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_send_timeout 1800;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
# 禁止其他管理后台接口外网访问
location /admin-api {
deny all;
}
# 禁止其他所有路径访问 - 直接拒绝
location / {
deny all;
}
}
# 内网访问配置 - 管理后台
server {
listen 443 ssl;
server_name admin.survey.example.com; # 内网域名
root /var/www/surveyking;
# SSL 配置
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# 允许所有管理后台页面访问
location / {
try_files $uri $uri/ /index.html;
}
# 单独处理 HTML 文件的缓存策略
location ~* \.(html|htm)$ {
# 禁用缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
# 可选:添加版本标识
add_header X-Version $date_gmt;
}
# 静态资源可以长期缓存(因为文件名带 hash)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 二维码代理
location /captcha {
# 修改为实际后端端口
proxy_pass http://localhost:1991/captcha;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 30m;
proxy_http_version 1.1;
proxy_set_header Connection close;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_send_timeout 1800;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
# 后端接口代理
location /admin-api {
# 修改为实际后端端口
proxy_pass http://localhost:1991/admin-api;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 30m;
proxy_http_version 1.1;
proxy_set_header Connection close;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_send_timeout 1800;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name survey.example.com admin.survey.example.com;
return 301 https://$server_name$request_uri;
}
支持的路由说明
外网允许访问的路径:
/e/:id
- 360 评价页面/s/:id
- 答卷页面/t/:id
- 练习页面/t/:id/:answerId
- 练习页面查看结果/s/:id/result/:resultId
- 公开查询/s/:id/exam-result/:answerId
- 考试结果与解析/s/:id/dimension/:answerId
- 考试结果与解析/s/:id/exam-certificate/:answerId
- 考试证书/s/:id/lottery/:answerId
- 抽奖页面/s/:id/red-packet-wheel/:answerId
- 红包转盘页面/s/:id/:answerId
- 查看问卷答案/s/:id/print/:answerId/:printId
- 打印报表/s/:id/vote-rank
- 投票排行榜/redeem/:projectId
- 兑奖页面/captcha
- 验证码接口/
- 根路径(重定向到首页)
外网允许访问的接口:
/admin-api/survey/*
- 问卷相关接口(提交答案、获取问卷等)/admin-api/lottery/*
- 抽奖相关接口(抽奖、兑奖等)/system/auth
- 认证接口(登录、验证等)
外网拒绝访问的路径:
/admin-api
- 其他管理后台接口(403 Forbidden)- 任何其他路径 - 直接拒绝(403 Forbidden)
域名配置要求
- 外网域名:
survey.example.com
- 用于答题页面访问 - 内网域名:
admin.survey.example.com
- 用于管理后台访问 - DNS 解析:确保两个域名都正确解析到服务器 IP
- SSL 证书:两个域名都需要配置 SSL 证书
安全说明
- 严格访问控制:外网域名只允许访问答题相关页面和必要的接口,其他路径都会被直接拒绝
- 必要接口开放:允许问卷、抽奖、认证等必要接口外网访问,确保答题功能正常
- 拒绝策略:使用
deny all
而不是return 404
,确保非授权访问被明确拒绝 - 管理功能隔离:核心管理 功能只能通过内网域名访问,确保数据安全
- 攻击防护:外网拒绝访问可以有效防止恶意扫描和攻击尝试
工作原理
工作原理目标
- 说明系统地址配置如何影响答题链接生成及内外网访问隔离
核心机制
-
链接生成逻辑
- 默认:读取当前页面
window.location.origin
- 配置后:优先使用系统地址配置的外网域名
- 适用于:答题链接、二维码、分享链接等
- 默认:读取当前页面
-
安全隔离架构
- 内网:管理后台、系统配置、数据统计
- 外网:答题页面、兑奖页面、公开查询
- 通过 Nginx 配置实现访问控制
配置生效流程
验证方法
- 浏览器控制台执行:
console.log(window.location.origin)
- 对比发布页面显示的答题链接域名
- 确认外网域名可正常访问答题页面
故障排查
常见问题
-
答题链接仍显示内网域名
- 检查系统地址配置是否正确保存
- 清理浏览器缓存后重新发布
- 确认配置的域名格式正确(包含协议)
-
外网无法访问答题页面
- 检查 Nginx 配置是否正确
- 确认域名 DNS 解析正常
- 验证后端服务端口配置
-
外网访问非目标路径被拒绝
- 这是正常的安全行为,外网只允许访问答题相关页面和必要接口
- 如需访问管理功能,请使用内网域名:
https://admin.survey.example.com
- 确认访问的路径是否在允许列表中
-
外网答题功能异常
- 检查问卷相关接口
/admin-api/survey/*
是否可正常访问 - 检查抽奖相关接口
/admin-api/lottery/*
是否可正常访问 - 检查认证接口
/system/auth
是否可正常访问 - 确认后端服务端口配置正确
- 检查问卷相关接口
-
管理后台无法访问
- 确认通过内网域名访问管理后台
- 检查内网 Nginx 配置是否正常