Files
ulthon_admin/extend/base/admin/middleware/CsrfMiddlewareBase.php

54 lines
2.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace base\admin\middleware;
use think\Request;
class CsrfMiddlewareBase
{
use \app\common\traits\JumpTrait;
public function handle(Request $request, \Closure $next)
{
if (env('adminsystem.IS_CSRF', true)) {
if (!in_array($request->method(), ['GET', 'HEAD', 'OPTIONS'])) {
// MCP 内部分发豁免(唯一豁免通道,安全性论证):
// 1. mcp_internal 标记只能由服务端写入 login 缓存McpDispatch 生成的一次性
// creator token攻击者需先具备服务器内部写缓存能力才可伪造
// 2. 跨站表单/HTML 场景无法携带 Authorization 自定义头(浏览器表单不透传该头),
// 对该头的 CSRF 攻击模型本身不成立;
// 3. 豁免标记与 5 分钟一次性 token 同生命周期McpDispatch 调用结束即删
// try/finally缓存 TTL 到期自动失效,不残留长期豁免通道。
$authorization = $request->header('authorization', '');
$token = (strpos($authorization, ' ') !== false) ? trim(explode(' ', $authorization)[1]) : '';
if (!empty($token)) {
$cached = \think\facade\Cache::store('login')->get($token);
if (!empty($cached['mcp_internal'])) {
return $next($request); // MCP 内部分发标记,跳过 CSRF一次性短时 token
}
}
// 跨域校验
$refererUrl = $request->header('REFERER', null);
$refererInfo = parse_url($refererUrl);
$host = $request->host(true);
if (!isset($refererInfo['host']) || $refererInfo['host'] != $host) {
$this->error('当前请求不合法!');
}
// CSRF校验
// @todo 兼容CK编辑器上传功能
$ckCsrfToken = $request->post('ckCsrfToken', null);
$data = !empty($ckCsrfToken) ? ['__token__' => $ckCsrfToken] : [];
$check = $request->checkToken('__token__', $data);
if (!$check) {
$this->error('请求验证失败,请重新刷新页面!');
}
}
}
return $next($request);
}
}