laravel生产环境必须立即修复三处安全漏洞:禁用调试模式并验证错误页不泄露信息、阻止/storage/logs和.env通过http访问、确保csrf防护正确启用;同时需配置csp头、禁用危险php函数及限制上传大小。

刚把Laravel项目部署到服务器,发现访问/storage/logs/laravel.log能直接下载日志、管理后台表单提交报419、甚至/.env文件被Nginx原样返回——这不是框架出问题,是生产环境安全配置缺了关键几项,必须立刻堵住这三处暴露面。
关闭调试模式并验证生效
APP_DEBUG=false只是第一步,漏掉任一关联配置都会让错误页继续泄露堆栈和SQL。
打开.env文件,确认三行同时存在且值正确:【APP_ENV=production、APP_DEBUG=false、APP_URL=https://yourdomain.com(注意必须带https://,否则SESSION_SECURE_COOKIE会失效)。
执行php artisan config:clear && php artisan config:cache,强制刷新缓存配置。
手动触发一个500错误:访问一个不存在的路由(如/trigger-500),页面必须显示简洁的“500 Server Error”,不能出现“Whoops”字样、文件路径、SQL语句或任何PHP变量dump。
检查storage/logs/目录权限是否为644,且Nginx配置中已加入location /storage/logs { deny all; },防止日志被HTTP直接读取。
收紧.env与storage目录权限
本地开发时.env权限宽松无感,但上线后若权限为644,Nginx以www-data身份运行时会直接把它当作静态文件返回——数据库密码、API密钥全暴露。
执行chmod 600 .env,确保只有文件所有者可读写,其他用户无任何权限。
运行ls -l .env确认输出形如-rw------- 1 www-data www-data,若属主不是www-data,先执行chown www-data:www-data .env。
【storage和bootstrap/cache目录必须由Web服务器用户完全掌控】:执行chown -R www-data:www-data storage bootstrap/cache,再设权限chmod -R 755 storage bootstrap/cache;其中storage/app子目录下的文件统一设为644,避免脚本误执行。
启用CSRF防护并校验中间件位置
Web路由的CSRF保护不是“默认开”,而是依赖中间件注册顺序——放错位置等于没开。
打开app/Http/Kernel.php,找到$middlewareGroups['web']数组,确认\App\Http\Middleware\VerifyCsrfToken::class存在,且【它必须在TrimStrings和ConvertEmptyStringsToNull之后、所有自定义中间件之前】。
检查所有Blade模板中的表单,每个<form></form>标签内部第一行必须是@csrf,包括AJAX请求封装的form、Vue组件内嵌的submit按钮对应form。
API路由若供浏览器内SPA调用(如管理后台),禁止归入api中间件组;改为显式声明->middleware(['web', 'auth:sanctum']),否则X-XSRF-TOKEN头不会注入cookie。
若需对特定路由豁免CSRF(如支付回调),在VerifyCsrfToken类中$except数组只加真实URL路径,例如'/webhook/stripe',严禁写'/webhook/*'这种宽泛通配。
动态注入Content-Security-Policy头
硬编码CSP策略上线后大概率导致JS白屏、字体加载失败——因为真实资源路径随路由名、用户角色、环境实时变化。
执行php artisan make:middleware InjectCspHeader,在handle()方法中写入:
$routeName = $request->route()?->getName() ?: 'fallback';
$role = $request->user()?->role ?? 'guest';
$nonce = base64_encode(random_bytes(16));
$policy = "default-src 'self'; script-src 'self'".($role === 'admin' ? " 'unsafe-inline'" : " 'nonce-{$nonce}'")."; img-src 'self' https:;";
将该中间件注册到app/Http/Kernel.php的web中间件组末尾,确保它在响应发出前最后执行。
测试时用浏览器开发者工具查看Response Headers,确认Content-Security-Policy字段存在且值含nonce-字符串;若为admin角色,检查控制台是否允许内联脚本执行。
禁用危险PHP函数并限制上传
宝塔面板或PHP.ini中未禁用exec、system等函数,等于给攻击者开了shell后门。
方法一:在宝塔面板PHP设置 → “禁用函数”栏,一次性填入:exec,system,passthru,shell_exec,popen,proc_open,eval,assert,curl_exec,curl_multi_exec,保存后重启PHP-FPM。
方法二:手动编辑/etc/php/8.1/fpm/php.ini(路径依PHP版本调整),找到disable_functions行,在其后追加上述函数,注意用英文逗号分隔,末尾不加逗号。
在nginx.conf或站点配置的server块内,添加上传限制:client_max_body_size 8m;、client_body_buffer_size 10K;,防止大文件上传耗尽内存。











