You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何加密URL中的用户ID以防止越权访问?

解决Laravel中URL用户ID泄露导致的越权访问问题

一、核心问题分析

你当前的路由直接暴露了自增用户ID(如/admin/edit/user/160),攻击者只需修改URL中的ID值就能访问其他用户数据,这属于直接对象引用漏洞。加密ID是隐藏真实ID的有效手段,但更关键的是配合权限验证,确保用户只能访问自己有权限操作的数据。

二、实现ID加密的两种可行方案

方案1:使用Laravel内置加密解密功能

Laravel自带安全的加密工具,无需额外依赖即可实现ID加密:

1. 生成加密后的编辑链接(在用户列表视图中)

在渲染编辑按钮时,对用户ID进行加密:

{{ route('edit.user', ['user_id' => encrypt($user->id)]) }}

2. 控制器中解密ID并查询用户

修改editUser方法,先解密ID再获取用户数据:

public function editUser($encrypted_id) {
    // 解密ID,若解密失败会自动抛出异常
    $user_id = decrypt($encrypted_id);
    
    $roles = Role::all();
    $alldivisions = Division::get();
    $alldistricts = District::get();
    $allpdivisions = Division::get();
    $allpdistricts = District::get();
    $bgroups = BloodGroup::get();
    $sscboards = SscBoard::get();
    $ocupations = Occupation::get();
    $editUser = User::findOrFail($user_id);

    // 强制权限验证:确保当前管理员有权编辑该用户
    $this->authorize('edit', $editUser);

    return view('admin.users.edit', compact('roles','editUser', 'ocupations', 'alldivisions', 'alldistricts', 'allpdivisions', 'allpdistricts', 'bgroups', 'sscboards'));
}

3. 更新请求中的ID处理

在updateUser方法中,对提交的加密ID做同样解密:

public function updateUser(Request $request) {
    $user_id = decrypt($request->id);
    $userToEdit = User::findOrFail($user_id);
    
    $this->authorize('save', $userToEdit);

    // 后续更新逻辑保持不变...
}

方案2:使用Hashids生成短加密串

Hashids可以生成短且无规律的字符串替代自增ID,更适合URL展示:

1. 安装Hashids扩展

composer require vinkla/hashids

2. 配置加密盐值(可选)

发布配置文件并设置自定义盐值,确保加密唯一性:

php artisan vendor:publish --provider="Vinkla\Hashids\HashidsServiceProvider"

修改config/hashids.php中的盐值:

'salt' => env('HASHIDS_SALT', 'your-unique-salt-string'),

3. 生成加密链接(视图中)

{{ route('edit.user', ['user_id' => Hashids::encode($user->id)]) }}

4. 控制器中解密ID

use Vinkla\Hashids\Facades\Hashids;

public function editUser($hashed_id) {
    // 解码后返回数组,取第一个元素为真实ID
    $user_id = Hashids::decode($hashed_id)[0];
    $editUser = User::findOrFail($user_id);

    $this->authorize('edit', $editUser);

    // 后续逻辑保持不变...
}

三、必须补充的权限验证

加密ID只是隐藏了真实ID,不能替代权限控制。你需要完善以下验证逻辑:

  • 创建UserPolicy定义权限规则:
    php artisan make:policy UserPolicy --model=User
    
    在UserPolicy中添加编辑权限规则示例:
    public function edit(User $authUser, User $user) {
        // 超级管理员可编辑所有用户,普通管理员只能编辑自己创建的用户
        return $authUser->role->is_super_admin || $authUser->id === $user->created_by;
    }
    
  • 在AuthServiceProvider中注册策略:
    protected $policies = [
        User::class => UserPolicy::class,
    ];
    

四、额外优化建议

  • 表单提交时传递加密后的ID,避免明文泄露
  • 保留Laravel默认的CSRF保护,防止跨站请求伪造
  • 记录异常访问日志(如解密失败、权限验证失败的请求)

内容的提问来源于stack exchange,提问作者H.M. Mohiuddin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:39:54