如何使用Sanctum安全加固Laravel API 仅允许自有站点访问
原有实现核心风险
- 固定账号密码硬编码在前端JS代码中,所有访问前端的用户都可以通过调试工具获取凭证,任意调用API接口
- Token存储在普通Cookie中,未做安全属性配置时容易被XSS、CSRF攻击窃取
优化方案(保留Bearer Token + Sanctum鉴权逻辑)
方案1:前端与Laravel服务同域/同根域名(最优)
直接使用Laravel Sanctum原生SPA鉴权能力,完全不需要硬编码任何凭证,也不需要自行实现Token申请逻辑:
- 在
config/sanctum.php的stateful配置项中添加前端域名,同时配置config/cors.php允许前端域名的跨域请求 - 前端发起接口请求前先调用
/sanctum/csrf-cookie接口初始化CSRF凭证,后续所有请求会自动携带会话Cookie与CSRF头,无需手动处理Token - 可单独为前端访问配置权限角色,和内部员工账号的权限做隔离,原有路由的
auth:sanctum中间件无需修改
方案2:前端与Laravel跨域,且前端有独立后端服务
所有鉴权凭证在服务端流转,完全不暴露给前端浏览器:
- 在Laravel端为API调用方生成专属Sanctum令牌,生成时指定令牌有效期、可访问的接口权限、允许调用的IP段,生成后的令牌仅存储在前端后端服务的环境变量中,禁止上传到代码仓库
- 前端浏览器需要调用接口时,先请求自有后端服务,由自有后端携带Sanctum令牌请求Laravel接口,再将结果返回给前端
- 可以直接删除原有的
/auth/token接口,避免账号密码泄露风险
方案3:前端为纯静态跨域站点,无后端服务
优化原有Token申请逻辑,避免硬编码凭证:
- 删除原有
/auth/token接口,不再使用账号密码申请Token - 在Laravel端配置CORS规则,仅允许自有前端域名发起API请求,非法域名直接拦截
- 生成专属Sanctum令牌,配置到前端构建工具的环境变量中,构建时注入到代码,禁止硬编码在源码中
- 存储Token的Cookie必须开启
HttpOnly、Secure、SameSite=Strict属性,避免被攻击窃取
额外安全加固
- 所有API路由添加
throttle中间件配置请求频率限制,避免被暴力调用 - 为Sanctum令牌配置接口权限,仅开放必要的
read、send能力,禁止访问内部员工相关接口 - 定期轮换API令牌,发现泄露立刻在Laravel端作废对应令牌
- 可选添加请求签名校验:前端每次请求将参数、时间戳、约定密钥做哈希生成签名,Laravel端校验签名合法性,即使Token泄露也无法正常调用接口
代码示例
Laravel路由配置
// 移除原有账号密码换Token的接口,添加频率限制 Route::middleware(['auth:sanctum', 'throttle:30,1'])->group(function () { Route::get('/get', [Api\ApiController::class, 'read']); Route::post('/send', [Api\ApiController::class, 'send']); });
生成专属Sanctum令牌
在Laravel项目根目录运行php artisan tinker后执行:
$apiUser = User::where('email', 'api@email.de')->first(); // 生成有效期7天、仅允许读写接口的令牌 $token = $apiUser->createToken('frontend-api', ['read', 'send'], now()->addDays(7))->plainTextToken; // 输出的$token保存到前端环境变量或自有后端配置中即可
接口权限校验
public function read(Request $request) { // 校验令牌是否有读权限 abort_if(!$request->user()->tokenCan('read'), 403); // 业务逻辑 } public function send(Request $request) { abort_if(!$request->user()->tokenCan('send'), 403); // 业务逻辑 }
内容的提问来源于stack exchange,提问作者Elias
相关产品推荐
相关产品推荐

