有时候我们不希望直接把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]
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
然后用hash_id进行查询