用户控制台定制开发指南
本文档面向二次开发者,介绍 JXWAF 云 WAF 用户控制台(jxwaf_user_console)的架构、部署对接、接口集成与二次开发方法。用户控制台为开源项目,企业可基于本指南自行定制或二次开发。
管理控制台(IT 运维团队)的操作请参考 操作指南(管理控制台),管理控制台对外自动化 API 请参考 API 调用。
一、产品定位
用户控制台是 JXWAF 云 WAF 面向 业务部门(子账号) 的自助管理平台,采用 Vue3 前端 + Go 后端 的薄代理架构:
- **Go 后端不负责业务数据存储,仅负责「会话管理 + 反向代理」,将所有业务请求转发至管理控制台的
/user/API - 所有业务数据存储在管理控制台,用户控制台本身不含数据库表结构(MySQL 仅为可选回退,见 部署配置)
- 新增业务功能时,需先确认管理控制台是否已提供对应
/user/接口
浏览器 ──► 用户控制台 Go 后端 ──(双 Token)──► 管理控制台 /user/ API
│ 本地路由 /api/*(仅会话 + CDN 预热/刷新)
└─ 会话(Cookie) / 登录注册 / 静态资源
核心推论
用户控制台本身不暴露业务 API,所有业务操作通过透传管理控制台 /user/ API 完成,路径与参数完全一致。
二、技术栈与目录结构
技术栈
| 层 | 技术 |
|---|---|
| 前端 | Vue 3(Composition API)、Vite、Element Plus、ECharts、vue-router、axios |
| 后端 | Go 1.24+,标准库 net/http,仅依赖 github.com/go-sql-driver/mysql |
| 构建 | build.sh(前端 npm build → static/,Go build,Docker build) |
目录职责
jxwaf_user_console/
├── main.go 入口:加载配置、装配路由、托管静态资源
├── internal/
│ ├── config.go 环境变量 → ServerConfig(必填校验)
│ ├── cloudapi.go CloudClient:Post/PostWithMainAuth,双 Token 鉴权
│ ├── handlers.go 【核心】所有 /api/* 路由注册与代理逻辑
│ ├── session.go SessionStore:内存会话 + Cookie + TTL 清理
│ ├── database.go 可选 MySQL:GetSubWafAuth / GetUserNameByWafAuth
│ └── response.go 统一响应:FailResponse / SuccessResponse / RawResponse
├── front-end/
│ └── src/
│ ├── main.js 入口(注册 Element Plus + 图标)
│ ├── App.vue 布局(侧边栏菜单 + Header),登录/注册页独立布局
│ ├── router/index.js 路由表(meta.requiresAuth 控制访问)
│ ├── views/ 页面组件(文件名 = 功能名,如 domain.vue)
│ ├── components/ 公共组件(MatchConditionBuilder.vue 等)
│ └── assets/scripts/common.js JXAjax 请求封装、校验函数、工具函数
└── static/ 前端构建产物(勿手改,由 build.sh 生成)
三、部署与配置
3.1 前置条件
- 已部署管理控制台,并完成:
- 创建网站接入配置(记录配置名,见 操作指南(管理控制台))
- 开启环境变量
USER_API_ENABLE=true(用户控制台需要管理控制台的/user/API)
- 获取主账号
waf_auth(管理控制台 系统管理 → 基础配置 查看)
3.2 环境变量
| 环境变量 | 必填 | 说明 |
|---|---|---|
CLOUD_API_URL | 是 | 管理控制台地址,如 http://<cloud_host>:8000 |
CLOUD_API_KEY | 是 | 主账号 waf_auth(第一层鉴权 Token) |
DEFAULT_WEBSITE_ACCESS_CONF | 是 | 默认接入配置名,注册子账号时自动绑定,需与管理控制台创建的配置名一致 |
HTTP_PORT | 否 | 监听端口,默认 80 |
MYSQL_HOST 等 | 否 | 可选:MySQL 连接(仅当管理控制台登录接口不返回 waf_auth 时需要) |
TZ | 否 | 时区,默认 Asia/Shanghai |
数据库是否必需?
- 管理控制台
/user/sub_account_login会返回子账号waf_auth→ 无需额外配置数据库(推荐,绝大多数场景) - 仅当管理控制台版本登录接口不返回
waf_auth时,才需配置数据库用于反查子账号waf_auth
3.3 部署步骤
# 1. 克隆仓库(也可通过 wget 下载源码包:wget https://github.com/jx-sec/jxwaf/archive/refs/heads/master.zip)
git clone --depth=1 https://github.com/jx-sec/jxwaf.git
# 2. 进入用户控制台目录,修改配置后启动
cd jxwaf/Cloud/jxwaf_cloud_user/
vim docker-compose.yml
docker compose up -d
部署完成后访问 http://<服务器IP>,业务部门即可注册账号并登录使用。
四、认证与会话机制
4.1 双层鉴权
用户控制台与管理控制台之间采用双层 Token 认证。/user/ 业务接口透传时,Go 后端自动注入两个请求头(开发者无需在前端请求中传递):
jxwaf-waf-auth: <主账号 waf_auth>(来自 CLOUD_API_KEY 配置)
jxwaf-sub-waf-auth: <子账号 waf_auth>(来自登录会话)
鉴权流程(由管理控制台执行):
- 通过
jxwaf-waf-auth反查主账号user_name - 通过
jxwaf-sub-waf-auth反查子账号sub_user_name及其所属主账号 - 校验子账号归属与主账号一致(防 Token 错配)
- 业务逻辑使用
user_name + sub_user_name作为数据隔离键
请求头使用连字符
请求头名称必须使用连字符 jxwaf-waf-auth / jxwaf-sub-waf-auth,带下划线的请求头会被丢弃。
4.2 本地会话
- 登录成功后,Go 后端创建内存 Session 并写入 Cookie
jxwaf_user_session(HttpOnly,TTL 24h,每次访问滑动续期) SessionStore为内存实现,重启即失效,不可横向扩展。如需集群部署,可自行替换为 Redis 等外部存储(修改internal/session.go)
五、本地 API 接口(/api/*)
用户控制台后端对外暴露少量本地接口,分为会话类与CDN 预热/刷新类。所有接口均为 POST + application/json。
5.1 会话类接口
| 接口 | 请求参数 | 响应 |
|---|---|---|
POST /api/login | sub_user_name, user_password, otp_auth_code(OTP 开启时必填) | {result, message, waf_auth} |
POST /api/register | sub_user_name, user_password, sub_otp_auth, otp_auth_code, otp_secret_key(website_access_conf 由后端注入,无需传) | {result, message: "register success", waf_auth} |
POST /api/logout | 无 | {result: true, message: "已退出登录"} |
POST /api/check_session | 无(读 Cookie) | {result: true, data: {sub_user_name}} |
POST /api/get_otp_qr_url | 无 | {result, message: "otpauth://...", otp_secret_key} |
登录流程:调用管理控制台 /user/sub_account_login(仅需主账号鉴权)→ 成功取 waf_auth → 创建本地 Session → 写 Cookie → 返回 {result, message, waf_auth}
注册流程:自动注入 website_access_conf = DEFAULT_WEBSITE_ACCESS_CONF → 调用管理控制台 /user/sub_account_register → 不创建会话(注册成功跳登录页)
OTP 二维码密钥由 Go 本地
crypto/rand生成(/api/get_otp_qr_url),不透传管理控制台。
5.2 CDN 预热 / 刷新接口
Go 后端将本地路径映射为管理控制台 /user/ 缓存接口后透传:
| 本地接口 | 管理控制台 /user/ 接口 | 说明 |
|---|---|---|
POST /api/cdn_warmup/list | /user/get_cache_warmup_list | 预热任务列表 |
POST /api/cdn_warmup/create | /user/create_cache_warmup_task | 创建预热任务 |
POST /api/cdn_warmup/detail | /user/get_cache_warmup_detail | 预热任务详情 |
POST /api/cdn_warmup/delete | /user/delete_cache_warmup_task | 删除预热任务 |
POST /api/cdn_refresh/list | /user/get_cache_refresh_list | 刷新任务列表 |
POST /api/cdn_refresh/create | /user/create_cache_refresh_task | 创建刷新任务 |
POST /api/cdn_refresh/detail | /user/get_cache_refresh_detail | 刷新任务详情 |
POST /api/cdn_refresh/delete | /user/delete_cache_refresh_task | 删除刷新任务 |
业务接口不走 /api/*
业务接口请直接使用 POST /user/*(见下节),/api/* 仅用于本地会话和 CDN 预热/刷新。
六、管理控制台 User API 集成(/user/*)
用户控制台的所有业务接口通过 POST /user/<接口名> 透传至管理控制台,路径与参数完全一致。以下为各业务模块的接口清单与关键参数。
6.1 统一响应格式
管理控制台响应经后端原样透传,四种格式:
| 类型 | 格式 |
|---|---|
| 操作成功 | {"result": true, "message": "..."} |
| 失败 | {"result": false, "message": "错误原因"} |
| 分页列表 | {"result": true, "records": [...], "page": 1, "total_pages": 5, "total_records": 250} |
| 单条详情 | {"result": true, "message": {对象}} |
分页约定:列表类接口 pageSize 固定 50;攻击事件/日志查询/业务明细固定 20。
6.2 账号与辅助
| 接口 | 请求参数 | 说明 |
|---|---|---|
/user/sub_account_login | sub_user_name, user_password, otp_auth_code | 登录验证,仅需主账号 Header |
/user/sub_account_register | sub_user_name, user_password, website_access_conf, sub_otp_auth, otp_auth_code, otp_secret_key | 注册,仅需主账号 Header,返回 {result, message, waf_auth} |
/user/edit_password | old_password, new_password | 修改密码 |
/user/get_account_info | 无 | 子账号基础信息 |
/user/get_waf_auth | 无 | 获取子账号 waf_auth |
/user/api_get_sub_account_list | 无 | 子账号列表(含 waf_auth),SOC 页筛选用 |
/user/api_get_global_name_list_list | 无 | 全局名单列表(规则匹配条件下拉用) |
6.3 域名管理
| 接口 | 请求参数 |
|---|---|
/user/get_domain_list | page |
/user/get_domain_search_list | page, search_domain |
/user/get_domain | domain |
/user/create_domain | domain, http, https, ssl_domain, source_ip(JSON数组串), source_http_port, source_https_port, origin_protocol, balance_type, pre_proxy, real_ip_conf, connect_timeout, send_timeout, read_timeout, detail |
/user/edit_domain | 同 create(domain 为 WHERE 条件) |
/user/delete_domain | domain |
create_domain 参数说明:
| 参数 | 说明 |
|---|---|
domain | 域名/IP,支持通配符(如 *.jxwaf.com) |
http / https | 是否启用 HTTP / HTTPS 协议("true"/"false") |
ssl_domain | HTTPS 时绑定的 SSL 证书域名 |
source_ip | 回源地址,JSON 数组串(如 ["1.2.3.4","1.2.3.5"]),支持 IP 与域名 |
source_http_port / source_https_port | HTTP/HTTPS 回源端口 |
origin_protocol | 回源协议:http / https / follow(协议跟随) |
balance_type | 负载均衡:round_robin(轮询)/ ip_hash(会话保持) |
pre_proxy | WAF 前是否存在代理("true"/"false") |
real_ip_conf | WAF 前存在代理时,获取真实 IP 的请求头(X-Real-IP / X-Forwarded-For) |
connect_timeout / send_timeout / read_timeout | 连接/发送/读取超时(秒) |
detail | 网站描述 |
get_domain_list 返回 records 字段:
| 字段 | 说明 |
|---|---|
sub_user_name, domain, detail | 子账号、域名、描述 |
http, https, ssl_domain | 协议与证书 |
source_ip, waf_update_source_ip | 原始回源地址、解析后的 IP 数组 |
source_http_port, source_https_port, origin_protocol, balance_type, pre_proxy, real_ip_conf | 回源与负载均衡配置 |
connect_timeout, send_timeout, read_timeout | 超时配置 |
cname | 系统生成的 CNAME 接入值(格式 <域名>.cname.<接入域名>) |
cname_status, cname_check_time | 接入状态("true" 已接入 / "false" 未接入)、检查时间 |
创建域名时,系统自动生成 CNAME 接入值。若部门已在用户控制台配置 DNS 自动接入,系统自动在 DNS 服务商创建 CNAME 记录,无需手动操作。
6.4 Web 安全防护
Web 引擎:
| 接口 | 请求参数 |
|---|---|
/user/get_web_engine_protection | 无 |
/user/edit_web_engine_protection | ai_protection, protection_mode, model_provider, model_api_key, engine_protection, unknown_request(至少一个) |
protection_mode:learn(模型训练)/business_priority(日常防护)/security_priority(重保防护)/offline(离线防护)unknown_request:未知请求处置(pass放行 /block拦截)engine_protection:语义分析防护(on开启 /watch观察 /off关闭)
Web 规则 / Web 白名单(各 7 个,结构一致):
| 接口 | 请求参数 |
|---|---|
get_web_rule_protection_list | page |
get_web_rule_protection | rule_name |
create_web_rule_protection | rule_name, rule_detail, rule_matchs, rule_action, action_value |
edit_web_rule_protection | 同 create |
delete_web_rule_protection | rule_name |
edit_web_rule_protection_status | rule_name, status("true"/"false") |
exchange_web_rule_protection_priority | rule_name, type("top"/"exchange")[, exchange_rule_name] |
- Web 规则
rule_action:block(阻断请求)/watch(观察模式) - Web 白名单
rule_action:web_white(Web 安全防护加白)/watch(观察模式) rule_matchs为匹配条件 JSON,前端必须使用 MatchConditionBuilder 组件构建,禁止手填 JSON
网页防篡改(8 个):参数同 Web 规则,额外字段 cache_page_url, cache_page_content, cache_content_type;另有 /user/waf_get_cache_page_url(cache_page_url)用于抓取页面内容。
6.5 流量安全防护
流量引擎:
| 接口 | 请求参数 |
|---|---|
/user/get_flow_engine_protection | 无 |
/user/edit_flow_engine_protection | engine_status, protection_plan, plans_config |
protection_plan:daily_observe(日常观察)/daily_protect(日常防护)/attack_protect(攻击防护)/emergency_protect(紧急防护)plans_config:各子模块(IP访问限制/IP数量限制/域名访问限制/SSL指纹防护/无差别紧急防护)的详细预案配置 JSON
流量规则 / 流量白名单(各 7 个,结构一致):
| 接口 | 请求参数 |
|---|---|
create_flow_rule_protection | rule_name, rule_detail, rule_matchs, rule_action, action_value, filter, entity, stat_time, exceed_count, block_time |
edit_flow_rule_protection_status | rule_name, status |
exchange_flow_rule_protection_priority | rule_name, type[, exchange_rule_name] |
- 流量规则
rule_action:block(阻断请求)/reject_response(拒绝响应)/watch(观察模式)/bot_check(人机识别)/network_block(网络封禁) stat_time:统计时间窗口(秒);entity:统计对象;exceed_count:请求次数阈值;block_time:处罚持续时间(秒)
IP 区域封禁:
| 接口 | 请求参数 |
|---|---|
/user/get_flow_ip_region_block | 无 |
/user/edit_flow_ip_region_block | ip_region_block, check_model, country_list(JSON数组串), block_action, action_value |
check_model:white(白名单模式)/black(黑名单模式)block_action:block/reject_response/watch/bot_check
6.6 SSL 证书
| 接口 | 请求参数 |
|---|---|
/user/get_ssl_manage_list | page |
/user/get_ssl_manage_search_list | page, search_ssl_domain |
/user/get_ssl_manage | ssl_domain |
/user/create_ssl_manage | ssl_domain, detail, private_key, public_key |
/user/edit_ssl_manage | 同 upload |
/user/delete_ssl_manage | ssl_domain |
/user/request_wildcard_cert | ssl_domain, dns_type, dns_api_key, dns_api_secret, auto_update, detail |
/user/retry_ssl_cert | ssl_domain |
/user/edit_ssl_cert_config | ssl_domain + DNS 配置字段 |
request_wildcard_cert 参数说明:
| 参数 | 说明 |
|---|---|
ssl_domain | 证书申请域名(系统自动添加 *. 前缀,输入 jxwaf.com 则申请 *.jxwaf.com) |
dns_type | DNS 服务商:aliyun / tencent / cloudflare |
dns_api_key / dns_api_secret | DNS 凭据(阿里云 AccessKey ID/Secret;腾讯云 SecretId/SecretKey;Cloudflare 仅 API Token,dns_api_secret 可空) |
auto_update | 是否自动续期("true"/"false") |
证书状态:success(已签发)/ pending(申请中)/ failed(申请失败)/ custom(已上传)/ none(未申请)。
6.7 CDN 缓存
缓存开关:
| 接口 | 请求参数 | 响应 |
|---|---|---|
/user/get_cache_switch | 无 | {result, message: {static_resource_cache, query_param_cache}} |
/user/edit_cache_switch | switch_name("static_resource_cache"/"query_param_cache"), switch_status("true"/"false") | {result, message: "edit success"} |
缓存策略 / 不缓存策略 / 缓存绕过策略(各 7 个,CRUD + 状态 + 优先级,结构同规则)。缓存策略额外含 cache_key(JSON 数组串,如 [{"key":"http_args","value":"path"}])。
预热/刷新任务接口见 5.2 CDN 预热/刷新接口。
6.8 安全运营(SOC)
攻击事件 / 日志:
| 接口 | 请求参数 |
|---|---|
/user/get_attack_event_list | from_time, to_time, page, domain(可选) |
/user/get_attack_behave_track | from_time, to_time, attack_ip, domain(可选) |
/user/get_log_query_list | from_time, to_time, page, sql_rules([{field,operation,value}]) |
Web/Flow 攻击统计(各 10 个):get_<web|flow>_attack_count_total / _count_trend / _api_count_total / _ip_count_total / _isocode_count_total / _api_top / _type_top / _ip_top / _isocode_top / _geoip,请求参数均为 from_time, to_time, domain(可选)。
count_total系列返回环比结构:{"result": true, "message": {"current": 1500, "previous": 1200, "trend": "up"}}
业务数据统计(数据源 MySQL,按子账号隔离,sub_user_name 由会话确定):
| 接口 | 请求参数 |
|---|---|
/user/get_soc_usage_stat_overview | from_time, to_time, domain(可选) |
/user/get_soc_usage_stat_qps_trend | 同 overview |
/user/get_soc_usage_stat_bandwidth_trend | 同 overview |
/user/get_soc_usage_stat_status_distribution | 同 overview |
/user/get_soc_usage_stat_latency_trend | 同 overview |
/user/get_soc_usage_stat_detail | from_time, to_time, domain(可选), page |
overview 响应字段:total_request, traffic_in, traffic_out, status_2xx, status_3xx, status_4xx, status_5xx, request_latency_avg, upstream_latency_avg, status_detail。
SOC 接口需主账号在管理控制台开启日志远程上报与安全报表配置。
七、前端定制开发
7.1 请求封装 JXAjax
所有后端请求必须走 assets/scripts/common.js 导出的 JXAjax,禁止裸用 axios:
import { JXAjax } from '../assets/scripts/common'
JXAjax('post', '/user/get_domain_list', { page: 1 },
function (response) {
// 成功:response.data 已保证 result === true
// 列表接口数据在 response.data.records / total_records
},
function () {
// 失败:已自动弹出错误提示,这里做业务回滚即可
}
)
JXAjax 内置行为(不要重复实现):
- 自动判断
result === true为成功 - 自动弹出成功/失败 ElMessage(
messageStatus: 'no-message'可静默) - 认证失效自动跳转登录页
- 登录成功(
/api/login)自动写本地登录态
7.2 匹配条件组件
涉及 rule_matchs 的页面必须使用 components/MatchConditionBuilder.vue(可视化匹配条件构建器),禁止让用户直接编辑 JSON。
7.3 新增前端页面(标准流程)
- 在
views/创建页面文件(参考同类已有页面,如web-rule-protection.vue) - 在
router/index.js注册路由(meta: { requiresAuth: true }) - 在
App.vue侧边栏菜单添加菜单项 - 调用接口:业务接口直接
JXAjax('post', '/user/<接口名>', ...),本地会话/预热刷新类才用/api/* - 校验:
npm run dev手测 +npm run build确认无编译错误
7.4 开发约定
- 命名:文件/函数/接口与管理控制台接口名保持一致;Go 函数用驼峰,前端文件用小写连字符
- 禁止暴露内部字段:用户界面不得出现
jxwaf_devid、waf_node_uuid、user_name等内部字段,需映射为中文标签 - 产品名:界面统一显示
JXWAF(全大写) - UI 一致性:复用 Element Plus 组件与既有页面的布局/间距/配色;统计类图表用折线图,单位与数值直接关联
- 不添加未要求的功能:只实现任务要求的页面/接口,不擅自加菜单或功能
八、后端定制开发
8.1 两种代理模式
| 模式 | 函数 | 用途 |
|---|---|---|
| 直连透传(会话) | genericUserProxy | 任意 /user/ POST 透传,需子账号会话双层鉴权 |
| 本地实现 | Login / Register / Logout / CheckSession / GetOtpQrUrl | 仅主账号鉴权或本地会话流程 |
8.2 新增接口流程
业务接口(绝大多数情况):
- 确认管理控制台
/user/接口存在 - 前端直接
JXAjax('post', '/user/<接口名>', ...)调用,无需改 Go 代码(genericUserProxy已覆盖所有/user/POST 透传)
本地接口(仅限会话类或需多资源映射):
- 在
handlers.go的RegisterRoutes中注册:mux.HandleFunc("/api/<名称>", h.<本地handler>) - 会话校验用
h.sessions.GetFromRequest(r),转发管理控制台用h.cloud.Post(path, body, session)或PostWithMainAuth - 编译验证:
go build ./...
业务接口不要在后端新写代理路由,直接走
/user/*透传;只有「本地会话相关」或「需要映射多资源」的接口才写专门 handler。
九、构建与验证
# 后端
go build ./...
go vet ./...
# 前端
cd front-end
npm install
npm run build # 编译校验(有语法/引用错误会失败)
# 整体
./build.sh binary # 仅 Go 二进制
./build.sh frontend # 仅前端
./build.sh # 全部
十、常见问题
| 问题 | 原因与解决 |
|---|---|
页面报 未登录或会话已过期 | Cookie 会话丢失/过期,重新登录;或接口错误地用了需会话的代理而页面未登录 |
接口返回 invalid jxwaf_sub_waf_auth | 子账号 waf_auth 失效:管理控制台重置过 waf_auth,需重新登录获取 |
登录报 认证服务暂时不可用 | 管理控制台 /user/sub_account_login 不可达:检查 CLOUD_API_URL、管理控制台 USER_API_ENABLE=true |
| 注册成功但登录提示无权限 | 注册未绑定接入配置:检查 DEFAULT_WEBSITE_ACCESS_CONF 是否与管理控制台配置一致 |
| 接口 404 | 业务接口:管理控制台无对应 /user/ 接口;本地接口:未在 RegisterRoutes 注册 |
| 登录态错乱 | 注册流程误调 setLoggedIn:注册成功只跳转登录页,不设置登录态 |
