简单加密通信插件
Pfinal Valkyrie - Webman 加密通信插件
动态全局请求/响应 AES-128-CBC 加解密,零代码接入,业务层无感知。
Webman 插件,给整个 HTTP 通信套一层透明加密层。前端引入 crypto.js 后,所有 fetch / axios / $.ajax / XHR 都会被自动加解密,业务代码完全无感知。
✨ 特性
- 零代码接入:前端引入一个
<script>即可,无需改任何业务代码 - 完整生态支持:
fetch / axios / $.ajax / layui.$.ajax / XHR全覆盖 - UTF-8 兼容:多语言、emoji 都不会乱码
- 动态配置:后台一键开关/切换模式,1s 内全 Worker 进程同步生效
- 多模式策略:
all / white / black / header四种路由匹配模式 - Header 覆盖:前端可单次请求
X-Crypto: 1强行走加密 - Webman 原生集成:基于中间件,挂载方式灵活
📦 安装
通过 admin 后台安装(推荐)
- 下载本插件 zip 包
- 解压到
/path/to/webman/plugin/pfinal_valkyrie - 进入 webman admin 后台 → 应用管理 → 找到
pfinal_valkyrie→ 点击「安装」
手动安装
# 把插件放到 webman/plugin/ 目录
cp -r pfinal_valkyrie /path/to/webman/plugin/
# 导入数据表
mysql -u root -p your_db < /path/to/webman/plugin/pfinal_valkyrie/crypto/install.sql
💡 首次安装默认密钥是
1234567890123456,生产环境请立即修改!
🚀 快速开始
Step 1:引入前端脚本
在业务页面 <head> 顶部引入:
<script src="/pfinal_valkyrie/crypto/crypto.js"></script>
然后正常写业务代码即可,无需改任何请求逻辑:
// crypto.js 会自动加密这个请求、自动解密响应
fetch('/api/user/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: '张三', password: '123456' })
}).then(r => r.json()).then(data => console.log(data));
// → 拿到的就是解密后的明文对象
Step 2:服务端启用中间件
在你想保护的 controller 上声明:
use support\Request;
class User
{
// 关键:声明中间件
protected $middleware = [
\plugin\pfinal_valkyrie\crypto\app\middleware\CryptoMiddleware::class,
];
public function login(Request $request)
{
// 拿到的就是解密后的明文
$params = $request->post();
return json(['code' => 0, 'msg' => 'ok', 'data' => $params]);
}
}
或者在主项目 config/middleware.php 全局启用:
return [
'' => [
\plugin\pfinal_valkyrie\crypto\app\middleware\CryptoMiddleware::class,
],
];
或者在路由组级别启用:
use Webman\Route;
Route::group('/api', function () {
Route::post('/user/login', 'app\controller\User@login');
// ...
})->middleware([
\plugin\pfinal_valkyrie\crypto\app\middleware\CryptoMiddleware::class,
]);
Step 3:打开后台开关
访问 admin 后台 → 安全配置 → 加解密配置 → 启用加密。
🧪 在线测试
插件内置完整测试页面:/valkyrie/crypto/test
覆盖:
- Echo 往返:明文 vs 加密 透明对比
- 登录模拟:admin / 123456
- 用户列表:分页 + 关键词查询
- 工具方法:直接调用
PfinalCrypto.encrypt / decrypt / wrapRequest
⚙️ 配置说明
后台「加解密配置」页可配置:
| 字段 | 说明 |
|---|---|
| 启用加密 | 总开关,关闭后中间件不工作 |
| AES 密钥 | 16 位字符(AES-128) |
| AES IV | 16 位字符(建议 16 位随机字符串) |
| 加密模式 | all 全局加密 / white 白名单 / black 黑名单 / header 纯 Header 控制 |
| 路由规则 | JSON 数组,支持通配符 *,仅 white/black 模式生效 |
| Header 覆盖 | 是否允许前端 X-Crypto: 0/1 单次覆盖 |
模式说明
| 模式 | 行为 |
|---|---|
all |
所有接口都加密(rules 字段无效) |
white |
只加密 rules 列表里的路径 |
black |
除了 rules 列表里的路径,其他都加密 |
header |
完全由前端请求头 X-Crypto: 1 决定 |
路由规则示例
["/api/user/*", "/api/order/*", "/api/payment/*"]
📡 协议说明
算法
- AES-128-CBC + PKCS7 Padding
- 字符集:UTF-8
请求格式
POST /api/user/login HTTP/1.1
Content-Type: application/json; charset=utf-8
X-Crypto: 1
X-Crypto-Encrypted: 1
{"_encrypted":true,"_data":"<base64(AES密文)>"}
响应格式
{"_encrypted": true, "_data": "<base64(AES密文)>"}
响应头会带 X-Crypto-Response: 1 标识。
🔧 高级用法
手动加解密
const Crypto = window.PfinalCrypto;
// 加密任意对象 → base64
const cipher = Crypto.encrypt({ username: '张三', password: '123456' });
// 包装请求体(等价于 { _encrypted: true, _data: cipher })
const wrapped = Crypto.wrapRequest({ foo: 'bar' });
// 解密 base64 → 还原对象
const plain = Crypto.decrypt(cipher);
// 解包响应(自动判断 _encrypted 标志)
const unwrapped = Crypto.unwrapResponse({ _encrypted: true, _data: cipher });
// 动态修改配置
Crypto.configure({
key: 'newkey123456789',
iv: 'newiv1234567890',
enabled: true,
debug: false
});
单次 Header 覆盖
// 无论当前 mode 是 white 还是 black,这条请求都会强制加密
fetch('/api/sensitive/data', {
headers: { 'X-Crypto': '1' },
// ...
});
// 这条请求强制不加密
fetch('/api/public/health', {
headers: { 'X-Crypto': '0' },
// ...
});
需要后台开启「Header 覆盖」开关才生效。
🗄️ 数据库
本插件使用一张配置表:
pfinal_valkyrie_crypto_config
├── id 主键
├── aes_key 16位 AES 密钥
├── aes_iv 16位 IV
├── enabled 0/1 总开关
├── mode all/white/black/header
├── rules JSON 数组
└── allow_header_override 0/1
⚠️ 本插件固定使用
plugin.admin.mysql连接。
这是 webman admin 生态的约定 —— webmanConfig::formatConfig()会把
plugin/admin/config/database.php里的mysql连接自动改名为plugin.admin.mysql。也就是说,本插件的加密配置表必须和 admin 插件的表在同一个数据库里
(plugin/admin/config/database.php里database字段指定的那个)。如果你想用独立的数据库,参考 admin 插件的
install.sql里的迁移方式,在自己的数据库里建一张
pfinal_valkyrie_crypto_config表,并修改 admin 插件的database配置(不推荐)。
🐛 调试
前端调试
把 debug: true 加上,浏览器控制台会输出 [PfinalCrypto] 开头的日志:
<script>
window.__PFINAL_CRYPTO_CONFIG__ = {
enabled: true,
debug: true // ← 打开
};
</script>
后端调试
中间件不生效时检查:
# 1. 确认中间件确实被加载
tail -f /path/to/webman/runtime/logs/pfinal_valkyrie.log
# 2. 确认请求带了正确的 header
# 浏览器 DevTools → Network → 选中请求 → Headers
# 应看到: X-Crypto: 1, X-Crypto-Encrypted: 1
# 3. 确认响应
# 响应体应是: {"_encrypted":true,"_data":"..."}
常见问题
Q1:admin 后台报 treetable.js: Cannot read properties of undefined (reading 'length')
A:crypto.js 没正确解密响应。检查是否把 crypto.js 放在业务脚本之前。
Q2:解密后中文字符乱码
A:本插件已用 TextEncoder/TextDecoder 处理 UTF-8,请确认浏览器版本 ≥ IE10(实际建议 Chrome 70+)。
Q3:测试页 /valkyrie/crypto/test 打不开
A:检查 TestApiController::page() 方法正常执行,浏览器 Network 面板看响应码。
📝 更新日志
v1.0.0 (2026-06)
- 🎉 首个稳定版本
- ✨ AES-128-CBC 加密 + UTF-8 兼容
- ✨ fetch / axios / XHR / jQuery 全覆盖
- ✨ 动态后台配置 + 1s 缓存
- ✨ 多种路由匹配模式
- ✨ 在线测试页面
- ✨ AES-128-CBC 加密 + UTF-8 兼容
- ✨ fetch / axios / XHR / jQuery 全覆盖
- ✨ 动态后台配置 + 1s 缓存
- ✨ 多种路由匹配模式
- ✨ 在线测试页面