laravel 对 ID 进行对称加密

有时候我们不希望直接把ID暴露给用户,因为有规则的ID,容易泄露信息,同时有可能被第三方直接遍历抓取资源。这时为了安全考虑,我们需要对ID进行加密解密。

laravel的一个对ID加密解密的扩展包地址:

https://github.com/vinkla/laravel-hashids

1.在laravel中安装hashids

composer require vinkla/hashids

2.在config/app.php中的providers数组中添加

\Vinkla\Hashids\HashidsServiceProvider::class, // hashids 加密

3.在config/app.php中的aliases数组中添加

'Hashids' => Vinkla\Hashids\Facades\Hashids::class,

4.在config下生成hashids.php配置文件

php artisan vendor:publish

5.修改hashids.php中的connections的盐值和加密输出长度

其中盐值可以是任意长度任意字符的字符串,加密和盐值有直接的关系,盐值是解密的钥匙。我直接取项目的密钥作为其盐值,以让项目统一,且不同项目的加密结果不一样。

'connections' => [
        'main' => [
            'salt' => env('APP_KEY'),
            'length' => '16',
        ],

        'alternative' => [
            'salt' => env('APP_KEY'),
            'length' => '6',
        ],

    ],

6.Hashids的加密解密使用方式

  • 加密的使用方式
Hashids::encode(123);//返回经过加密后的字符串8R1KGlogar2mEwZY
  • 解密的使用方式
    注意返回值是数组
Hashids::decode('8R1KGlogar2mEwZY');//返回经过解密后的数组[123]
  • 同时加密多个参数
Hashids::encode(1,2,3);//vY75j7ZikId2gd0e
  • 解密多个参数的加密字符串
Hashids::decode('vY75j7ZikId2gd0e')//返回经过解密后的数组[1,2,3]
  • 切换不同的盐值和加密长度
    我们可能需要对多个不同类型的id进行加密,盐值和返回长度也各有不同。所以config的hashids中的多个数组可以派上用场了。其中main数组是作为默认连接,可以自行添加其他的加密数组。
Hashids::connection('alternative')->encode(1);
Hashids::connection('alternative')->decode("XjpG2d");

实际应用:

(1)、先创建一个中间件

php artisan make:middleware Hashids

修改handle方法: 

public function handle($request, Closure $next)
    {
        //对show,update方法的ID进行解密处理
        if (str_contains($request->route()->getActionName(), ['show', 'update'])) {
            $route = $request->route()->uri();  // 如:api/user/{user}
            $route_arr = explode('/', $route);
            $uri = $request->getRequestUri();  // 如:/api/user/12
            $uri = ltrim($uri, '/');
            $uri_arr = explode('/', $uri);

            $ids = array_values(array_diff($uri_arr, $route_arr)); //获取差集,并将索引重置
            $id = \Hashids::decode($ids[0]);  //解密
            $names = array_values(array_diff($route_arr, $uri_arr)); //获取差集,并将索引重置
            $name = trim($names[0], '{}');//获取参数名
  
            $router = \Route::current(); //获取当前路由实例
            //这里ID由于加密后又解密变成了数组,所以取$id[0],暂时还没有更好的解决方案
            $router->setParameter($name, $id[0]); //设置当前路由的参数id为解密后的数字

        }
        return $next($request);
    }

(2)、在app\Http\Kernel.php文件的$routeMiddleware数组中添加

'hashids' => \App\Http\Middleware\Hashids::class,

(3)、修改路由,加入中间件

Route::group(['middleware' => ['auth:api','hashids']], function () {
    Route::resources([
        'user' => 'UserController',
    ]);
});

(4)、修改模型,进行加密

//添加表中不存在的字段,自定义字段
protected $appends = ['hash_id'];

public function getHashIdAttribute()
{
     return \Hashids::encode($this->attributes['id']);
}

(5)、控制器里面访问

public function show($id)
 {
        if (empty($id)) {
            return response()->json([
                'message' => '参数错误!!'
            ], 403);
        }
        $user = User::find($id);
        if($user) {
            $user->roles;
        }

        return response()->json([
            'message' => '请求成功',
            'data' => $user ?: []
        ], 200);

 }

(6)、 先访问列表,获取对应的hash_id

laravel 对 ID 进行对称加密_第1张图片

然后用hash_id进行查询 

laravel 对 ID 进行对称加密_第2张图片

 

你可能感兴趣的:(php,laravel)