定义了两个中间件:
DesensitizeMiddleware
响应数据注解脱敏中间件ResponseCaseConverter
响应数据下划线转驼峰现出现一个问题:当我定一个字段id_card
,数据脱敏并将字段名变成idCard
,这个时候,就不能脱敏成功,需将ResponseCaseConverter
移除掉,才能正常响应脱敏
中间件配置:
<?php
return [
'@' => [
\Landao\WebmanCore\Middleware\DesensitizeMiddleware::class,
\Landao\WebmanCore\Middleware\ResponseCaseConverter::class
]
];
DesensitizeMiddleware
代码:
<?php
namespace Landao\WebmanCore\Middleware;
use Landao\WebmanCore\Helpers\DesensitizeHelper;
use Landao\WebmanCore\ParseAnnotation\DesensitizeParse;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
/**
* 注解脱敏中间件
*/
class DesensitizeMiddleware implements MiddlewareInterface
{
/**
* 响应数据的根路径
* @var string
*/
protected $rootPath = 'data';
public function process(Request $request, callable $handler): Response
{
// 先执行后续中间件和控制器,获取响应
$response = $handler($request);
// 获取当前控制器和方法
$controller = $request->controller;
$action = $request->action;
// 获取脱敏规则
$desensitizeRules = DesensitizeParse::getDesensitizeRules($controller, $action);
if (empty($desensitizeRules)) {
return $response;
}
// 尝试解析响应内容
$content = $response->rawBody();
$data = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return $response;
}
// 支持根路径配置(如API响应格式为 {code:200, data:{...}})
$targetData = &$data;
if (!empty($this->rootPath)) {
$rootFields = explode('.', $this->rootPath);
foreach ($rootFields as $field) {
if (!isset($targetData[$field])) {
// 根路径不存在,记录日志并返回原始响应
return $response;
}
$targetData = &$targetData[$field];
}
}
// 应用脱敏规则
if (is_array($targetData)) {
// 根数据是数组,遍历每个元素处理
foreach ($targetData as &$item) {
if (is_array($item)) {
$this->processArrayItem($item, $desensitizeRules);
}
}
} else {
// 根数据是对象,直接处理
foreach ($desensitizeRules as $rule) {
$this->applyDesensitize($targetData, $rule['field'], $rule['rule']);
}
}
$response->withBody(json_encode($data, JSON_UNESCAPED_UNICODE));
// 更新响应内容
return $response;
}
}
ResponseCaseConverter
代码:
<?php
namespace Landao\WebmanCore\Middleware;
use Landao\WebmanCore\Helpers\CamelHelper;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\Middleware;
/**
* 响应数据下划线转驼峰
*/
class ResponseCaseConverter extends Middleware
{
public function process(Request $request, callable $handler): Response
{
// 先执行后续中间件获取响应
$response = $handler($request);
// 只处理JSON响应
$contentType = $response->getHeader('Content-Type');
if (strpos($contentType, 'application/json') !== false) {
$body = $response->rawBody();
$data = json_decode($body, true);
// 检查JSON解码是否成功
if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
// 使用CamelHelper转换键名
$convertedData = CamelHelper::recursiveConvertNameCaseToCamel($data);
// 更新响应内容
$newBody = json_encode($convertedData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
$response = $response->withBody($newBody);
}
}
return $response;
}
}
是中间件顺序配置错了吗?或者有没有更好的不侵入代码,去处理这两个业务?
中间件是洋葱模型