CodeIgniter 4 安全创建和发送 Cookie 需显式配置 secure=false(开发环境)、cookie_path='/’,并用 $response->setCookie() 发送;跨域预检需 CorsFilter 返回 200 并设全量 CORS 头;Vite 代理需 changeOrigin: true 且前端请求用 /api 路径。

CodeIgniter 4 怎么安全创建和发送 Cookie
CI4 的 Cookie 类不是简单 setcookie() 封装,它默认启用 Secure、HttpOnly 和 SameSite=Lax,但这些行为必须匹配实际部署环境,否则 Cookie 在浏览器里根本不会被存储或发送。
- 开发时若用
http://localhost(非 HTTPS),必须显式关掉secure:传入['secure' => false],否则 Chrome/Firefox 直接忽略该 Cookie -
cookie_path必须设为'/',尤其在多语言子路径(如/zh/)场景下;设成'/zh/'会导致切换语言后 Cookie 不随请求发出 - 若前端带凭证(如
fetch(..., { credentials: 'include' })),后端响应必须含Access-Control-Allow-Credentials: true,且此时Access-Control-Allow-Origin不能是*,得写死前端域名(如http://localhost:5173) - 用
cookie()辅助函数创建 Cookie 时,它只构造对象,不自动发送;必须配合$response->setCookie($cookie)才生效
为什么 CI4 跨域请求总卡在 OPTIONS 预检
这不是 CI4 的 bug,而是浏览器强制执行的 CORS 预检机制 —— 只要请求含自定义头(如 Authorization)、非简单方法(如 PUT)、或 Content-Type 为 application/json,就先发一个 OPTIONS 请求试探后端是否允许。CI4 默认不处理 OPTIONS,直接 404 或 500,前端就卡住。
- 最稳做法:写个
CorsFilter,在app/Filters/CorsFilter.php里对OPTIONS请求直接返回 200,并设置Access-Control-Allow-Methods、Access-Control-Allow-Headers等头 - 别在控制器里手动
header(),因为 CI4 响应生命周期中,header()可能被后续中间件覆盖或触发“headers already sent”错误 -
Access-Control-Allow-Headers必须明确列出前端实际用的头,比如Authorization,X-Requested-With,Content-Type;写*在带凭据时无效 - 生产环境别留
Access-Control-Allow-Origin: *,它和credentials: true冲突,浏览器会直接拒绝响应
Vite 开发时怎么让 /api 请求不跨域
本地开发阶段,代理比改后端 CORS 更干净——浏览器根本不知道有跨域这回事,所有请求都发给 http://localhost:5173(Vite 地址),Vite 自动把 /api/ 开头的请求转发到 CI4(比如 http://localhost:8000)。
- Vite 配置里
server.proxy必须设changeOrigin: true,否则 CI4 收到的Host头还是localhost:5173,可能触发域名白名单拦截 - 前端代码里所有 API 路径写相对路径:
axios.get('/api/users'),而不是axios.get('http://localhost:8000/api/users') - CI4 启动命令别用
php spark serve绑定127.0.0.1,改用php spark serve --host 0.0.0.0,否则 Vite 代理连不到 - 代理只在开发生效,打包后的
dist目录上线必须配 Nginx 反向代理,否则静态资源和 API 会分属不同域名
CI4 控制器里怎么读取和验证 Cookie
CI4 的 $this->request->getCookie() 只读原始值,不校验签名;真正安全的读取方式是用 $this->response->getCookie() 或服务容器里的 Cookie 实例,它们会自动校验 __ci_last_regenerate 和加密签名。
- 不要用
$_COOKIE['xxx']直接读,它绕过 CI4 的加密/签名机制,容易被篡改 - 若 Cookie 是用
cookie()->withValue(...)->withPrefix('__Secure-')创建的,读取时必须用相同 prefix:$this->request->getCookie('remember_token', '__Secure-') - CSRF token 默认也存在 Cookie 里(
csrf_cookie_name),前后端分离时,前端需在请求头带上这个值:headers: { 'X-CSRF-TOKEN': cookieValue },CI4 才会放行 POST/PUT/DELETE - Cookie 过期时间由服务端控制,但浏览器也可能因隐私策略(如 Safari ITP)提前丢弃第三方 Cookie,别依赖它做长期登录态
credentials 开关、SameSite 策略、Secure 标志、甚至前端 fetch 的 mode 选项,任意一环没对齐,整条链就断。


















