64 lines
13 KiB
JavaScript
64 lines
13 KiB
JavaScript
import{_ as a,o as n,c as i,a2 as e}from"./chunks/framework.B-QBKwc1.js";const o=JSON.parse('{"title":"中间件执行顺序","description":"本页展示请求在框架中的完整中间件执行流程,包括全局中间件和应用中间件的执行顺序,帮助开发者理解请求处理链路。","frontmatter":{},"headers":[],"relativePath":"zh/appendix/middleware.md","filePath":"zh/appendix/middleware.md"}'),p={name:"zh/appendix/middleware.md"};function t(l,s,d,h,r,c){return n(),i("div",null,[...s[0]||(s[0]=[e(`<h1 id="F-中间件执行顺序" tabindex="-1">F. 中间件执行顺序 <a class="header-anchor" href="#F-中间件执行顺序" aria-label="Permalink to "F. 中间件执行顺序""></a></h1><div class="tip custom-block"><p class="custom-block-title">概述</p><p>本页展示请求在框架中的完整中间件执行流程,包括全局中间件和应用中间件的执行顺序,帮助开发者理解请求处理链路。</p></div><h2 id="执行流程图" tabindex="-1">执行流程图 <a class="header-anchor" href="#执行流程图" aria-label="Permalink to "执行流程图""></a></h2><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>请求进入</span></span>
|
||
<span class="line"><span> │</span></span>
|
||
<span class="line"><span> ▼</span></span>
|
||
<span class="line"><span>┌────────────────┐</span></span>
|
||
<span class="line"><span>│ProxyMiddleware │ 全局中间件(最先执行)</span></span>
|
||
<span class="line"><span>│ │ 从代理头提取真实客户端 IP</span></span>
|
||
<span class="line"><span>└──────┬─────────┘</span></span>
|
||
<span class="line"><span> │</span></span>
|
||
<span class="line"><span> ▼</span></span>
|
||
<span class="line"><span>┌──────────────┐</span></span>
|
||
<span class="line"><span>│CorsMiddleware│ 全局中间件</span></span>
|
||
<span class="line"><span>│ │ 处理 OPTIONS 预检 + 跨域响应头</span></span>
|
||
<span class="line"><span>└──────┬───────┘</span></span>
|
||
<span class="line"><span> │</span></span>
|
||
<span class="line"><span> ▼</span></span>
|
||
<span class="line"><span>┌──────────────┐ 401</span></span>
|
||
<span class="line"><span>│AuthMiddleware│──────────► 未认证(Token 缺失/无效/过期)</span></span>
|
||
<span class="line"><span>│ │ 403</span></span>
|
||
<span class="line"><span>│ JWT认证 │──────────► 无权限</span></span>
|
||
<span class="line"><span>│ 权限校验 │</span></span>
|
||
<span class="line"><span>└──────┬───────┘</span></span>
|
||
<span class="line"><span> │ 注入 userInfo</span></span>
|
||
<span class="line"><span> ▼</span></span>
|
||
<span class="line"><span>┌──────────────┐ 403</span></span>
|
||
<span class="line"><span>│TenantMiddleware│──────────► 租户异常(禁用/过期)</span></span>
|
||
<span class="line"><span>│ │</span></span>
|
||
<span class="line"><span>│ 租户上下文 │</span></span>
|
||
<span class="line"><span>└──────┬───────┘</span></span>
|
||
<span class="line"><span> │ 注入 tenantId, tenantInfo</span></span>
|
||
<span class="line"><span> ▼</span></span>
|
||
<span class="line"><span>┌──────────────┐ 403</span></span>
|
||
<span class="line"><span>│DemoMiddleware│──────────► 演示环境禁止写操作</span></span>
|
||
<span class="line"><span>└──────┬───────┘</span></span>
|
||
<span class="line"><span> │</span></span>
|
||
<span class="line"><span> ▼</span></span>
|
||
<span class="line"><span>┌──────────────┐</span></span>
|
||
<span class="line"><span>│ LogMiddleware│ 记录操作日志(写操作始终记录)</span></span>
|
||
<span class="line"><span>└──────┬───────┘</span></span>
|
||
<span class="line"><span> │</span></span>
|
||
<span class="line"><span> ▼</span></span>
|
||
<span class="line"><span>┌──────────────┐</span></span>
|
||
<span class="line"><span>│ 控制器方法 │</span></span>
|
||
<span class="line"><span>└──────────────┘</span></span></code></pre></div><h2 id="中间件职责" tabindex="-1">中间件职责 <a class="header-anchor" href="#中间件职责" aria-label="Permalink to "中间件职责""></a></h2><table tabindex="0"><thead><tr><th>中间件</th><th>类型</th><th>职责</th><th>配置</th></tr></thead><tbody><tr><td>ProxyMiddleware</td><td>全局</td><td>代理头解析,提取真实客户端 IP</td><td>.env → <code>[API]</code> PROXY_IPS</td></tr><tr><td>CorsMiddleware</td><td>全局</td><td>跨域处理</td><td>config/cors.php</td></tr><tr><td>AuthMiddleware</td><td>路由级</td><td>JWT 认证 + 权限校验</td><td>config/middleware.php → auth_except</td></tr><tr><td>TenantMiddleware</td><td>路由级</td><td>租户上下文注入</td><td>内置排除列表</td></tr><tr><td>DemoMiddleware</td><td>路由级</td><td>演示环境拦截</td><td>.env → [APP] DEMO</td></tr><tr><td>LogMiddleware</td><td>路由级</td><td>操作日志记录</td><td>config/middleware.php → log_except</td></tr></tbody></table><h2 id="排除配置" tabindex="-1">排除配置 <a class="header-anchor" href="#排除配置" aria-label="Permalink to "排除配置""></a></h2><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// config/middleware.php</span></span>
|
||
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">return</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">auth_except</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> =></span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">login</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">captcha</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">oauth2/token</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">oauth2/check/token</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> ],</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">log_except</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> =></span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">login</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">logout</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">captcha</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">oauth2</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
|
||
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> ],</span></span>
|
||
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span></code></pre></div><h2 id="注入内容" tabindex="-1">注入内容 <a class="header-anchor" href="#注入内容" aria-label="Permalink to "注入内容""></a></h2><table tabindex="0"><thead><tr><th>中间件</th><th>注入字段</th><th>说明</th></tr></thead><tbody><tr><td>ProxyMiddleware</td><td><code>$_SERVER['REMOTE_ADDR']</code></td><td>覆盖为真实客户端 IP</td></tr><tr><td>AuthMiddleware</td><td><code>$request->userInfo</code></td><td>用户信息(uid, username, type 等)</td></tr><tr><td>TenantMiddleware</td><td><code>$request->tenantId</code></td><td>租户 ID(0=超级管理员)</td></tr><tr><td>TenantMiddleware</td><td><code>$request->isSuperAdmin</code></td><td>是否超级管理员</td></tr><tr><td>TenantMiddleware</td><td><code>$request->tenantInfo</code></td><td>租户信息对象</td></tr></tbody></table><h2 id="ProxyMiddleware-详解" tabindex="-1">ProxyMiddleware 详解 <a class="header-anchor" href="#ProxyMiddleware-详解" aria-label="Permalink to "ProxyMiddleware 详解""></a></h2><p>当项目部署在 CDN / 负载均衡 / Nginx 反向代理后面时,PHP 的 <code>REMOTE_ADDR</code> 是代理服务器的 IP(通常是 <code>127.0.0.1</code>),真实客户端 IP 由代理通过 <code>X-Forwarded-For</code> / <code>X-Real-IP</code> 请求头传递。</p><h3 id="工作原理" tabindex="-1">工作原理 <a class="header-anchor" href="#工作原理" aria-label="Permalink to "工作原理""></a></h3><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>客户端(真实IP) → CDN/代理 → Nginx → PHP-FPM</span></span>
|
||
<span class="line"><span> ↓ 设置头</span></span>
|
||
<span class="line"><span> X-Forwarded-For: 真实IP, 代理IP</span></span>
|
||
<span class="line"><span> X-Real-IP: 真实IP</span></span></code></pre></div><ol><li>检查 <code>REMOTE_ADDR</code> 是否在受信代理列表(<code>.env</code> → <code>PROXY_IPS</code>)</li><li>如果是,从 <code>X-Real-IP</code> 或 <code>X-Forwarded-For</code> 头提取真实 IP</li><li>覆盖 <code>$_SERVER['REMOTE_ADDR']</code>,后续 <code>request()->ip()</code> 返回真实 IP</li></ol><h3 id="配置" tabindex="-1">配置 <a class="header-anchor" href="#配置" aria-label="Permalink to "配置""></a></h3><div class="language-ini vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ini</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># .env [API] 段</span></span>
|
||
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 受信代理 IP(逗号分隔,支持 CIDR 网段)</span></span>
|
||
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 未配置时默认信任 127.0.0.1 和 ::1</span></span>
|
||
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">PROXY_IPS</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> 127.0.0.1,::1,101.226.0.0/15,180.101.0.0/16</span></span></code></pre></div>`,17)])])}const g=a(p,[["render",t]]);export{o as __pageData,g as default};
|