Files
rxthinkcmf-wiki/RXThinkCMF_ThinkPhp6_EleVue/.vitepress/dist/assets/zh_appendix_middleware.md.CmbJWEbW.lean.js
T
2026-10-25 18:52:36 +08:00

64 lines
13 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
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 &quot;F. 中间件执行顺序&quot;">​</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 &quot;执行流程图&quot;">​</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 &quot;中间件职责&quot;">​</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 &quot;排除配置&quot;">​</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;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">auth_except</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> =&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">login</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">captcha</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">oauth2/token</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">oauth2/check/token</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</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;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">log_except</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> =&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">login</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">logout</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">captcha</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">oauth2</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</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 &quot;注入内容&quot;">​</a></h2><table tabindex="0"><thead><tr><th>中间件</th><th>注入字段</th><th>说明</th></tr></thead><tbody><tr><td>ProxyMiddleware</td><td><code>$_SERVER[&#39;REMOTE_ADDR&#39;]</code></td><td>覆盖为真实客户端 IP</td></tr><tr><td>AuthMiddleware</td><td><code>$request-&gt;userInfo</code></td><td>用户信息(uid, username, type 等)</td></tr><tr><td>TenantMiddleware</td><td><code>$request-&gt;tenantId</code></td><td>租户 ID(0=超级管理员)</td></tr><tr><td>TenantMiddleware</td><td><code>$request-&gt;isSuperAdmin</code></td><td>是否超级管理员</td></tr><tr><td>TenantMiddleware</td><td><code>$request-&gt;tenantInfo</code></td><td>租户信息对象</td></tr></tbody></table><h2 id="ProxyMiddleware-详解" tabindex="-1">ProxyMiddleware 详解 <a class="header-anchor" href="#ProxyMiddleware-详解" aria-label="Permalink to &quot;ProxyMiddleware 详解&quot;">​</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 &quot;工作原理&quot;">​</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[&#39;REMOTE_ADDR&#39;]</code>,后续 <code>request()-&gt;ip()</code> 返回真实 IP</li></ol><h3 id="配置" tabindex="-1">配置 <a class="header-anchor" href="#配置" aria-label="Permalink to &quot;配置&quot;">​</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};