Laravel 6.0 无外部认证API时如何防护第三方跳转路由避免越权
路由防护最优解决方案
核心方案:基于共享密钥的HMAC签名校验
你的场景核心问题是路径参数可篡改、Referer校验可伪造,而你方可以控制外部系统的跳转链接生成逻辑,因此使用签名校验是成本最低、安全性最高的方案,无需依赖外部系统提供身份API。
实现逻辑
- 外部学生系统和你的Laravel应用提前约定唯一加密密钥,存储在两边的环境变量中,禁止明文泄露
- 外部系统生成跳转链接时,将学生标识参数(ra、email)、链接生成时间戳、约定密钥一同做HMAC哈希运算得到签名值,将签名作为额外参数附加到跳转链接
- Laravel端收到请求后先校验签名合法性、链接有效期,校验通过才允许执行业务逻辑,只要用户修改任意参数,签名就会失效,直接拦截请求
代码修改示例
- 路由修改(改为查询参数传递,避免路径参数篡改):
Route::get('office365', 'PortalOffice\PortalOfficeController@index')->name('portaloffice.usuario');
- 控制器逻辑修改:
public function index(Request $request) { // 校验必要参数是否存在 if (!$request->has(['ra', 'email', 'timestamp', 'sign'])) { return view('errors.403'); } // 读取约定的加密密钥,配置在.env文件中:EXTERNAL_SYSTEM_SECRET=你的自定义密钥 $secret = env('EXTERNAL_SYSTEM_SECRET'); $ra = $request->input('ra'); $email = $request->input('email'); $genTime = $request->input('timestamp'); $userSign = $request->input('sign'); // 校验链接有效期,示例设置为10分钟内有效,可根据业务调整 if (time() - $genTime > 600 || $genTime > time()) { return view('errors.403'); } // 生成校验签名,拼接规则必须和外部系统完全一致 $checkContent = "ra={$ra}&email={$email}×tamp={$genTime}"; $validSign = hash_hmac('sha256', $checkContent, $secret); // 防时序攻击的签名比对 if (!hash_equals($validSign, $userSign)) { return view('errors.403'); } // 原有业务逻辑 $usuario = UsuariosMicrosoft::where('login', '=', $ra)->get(); return view('portaloffice.pagina', compact('ra', 'email', 'usuario')); }
额外优化建议
- 原有Referer校验逻辑可保留,作为额外防护层
- 如需更高安全性,可将生成的签名和对应ra存入缓存,设置相同有效期,校验通过后立即删除缓存,实现一次性链接,避免链接泄露后被复用
- 加密密钥定期更换,不要硬编码在业务代码中
内容的提问来源于stack exchange,提问作者calebe santana
相关产品推荐
相关产品推荐

