资讯专栏INFORMATION COLUMN

使用Hashids来保护你的数据库主键

jk_v1 / 2992人阅读

摘要:使用注意该库并不是一个加密库,所以不建议用来加密敏感数据,我们的数据库主键并不是业务上的敏感数据,所以这个没关系。

为什么要保护数据库主键?

数据库主键一般是有序自增主键,极易被爬虫抓取数据,作为应用开发者,这是不应该的,你辛辛苦苦收集的数据转眼之间被其他人给抓取了,是不是很大的损失?

Hashids的介绍
generate short unique ids from integers

理解为数字编码库即可,几乎支持市面上所有语言。

available in JavaScript, Ruby, Python, Java, Scala, PHP, Perl, Perl 6, Swift, Clojure, Objective-C, C, C++11, D, F#, Go, Erlang, Lua, Haskell, OCaml, Elixir, Rust, Smalltalk, ColdFusion, Groovy, Kotlin, Nim, VBA, Haxe, Crystal, Elm, ActionScript, CoffeeScript, Bash, R, TSQL, PostgreSQL and for
PHP使用
$hashids = new HashidsHashids("this is my salt");
$id = $hashids->encode(1, 2, 3);
$numbers = $hashids->decode($id);
注意

该库并不是一个加密库,所以不建议用来加密敏感数据,我们的数据库主键ID并不是业务上的敏感数据,所以这个没关系。

Yii2的使用

由于该编解码是独立与业务之外的,所以需要处理的地方在下面:

接收请求数据的自动解码

响应数据的自动编码(本文只针对JSON响应处理,有需要的可以添加ResponseFormatter自行处理)

这两个步骤不应该提现在控制器中,控制器拿到的数据是解码好的,响应的数据是原始数据,然后我们在响应中处理。

代码 助手类(HashidsHelper)
class HashidsHelper {
    public static function encode($id)
    {
        $hashids = new HashidsHashids("salt",16);
        return $hashids->encode($id);
    }

    public static function decode($hash)
    {
        $hashids = new HashidsHashids("salt",16);
        $data= $hashids->decode($hash);
        return empty($data)?null:$data;
    }

    public static function decodeArray(array $hashes)
    {
        return array_map([HashidsHelper::class, "decode"], $hashes);
    }
/**
     * 递归编码
     * @param array $data
     */
    public static function encodeRecursive(array &$data)
    {
        foreach ($data as $key => &$value) {
            if (is_array($value)) {
                self::encodeRecursive($value);
                continue;
            }
            if (strpos($key, "id") !== false && is_numeric($value)) {
                $data[$key] = static::encode($value);
            }
        }
    }

    /**
     * 递归解码
     * @param array $data
     */
    public static function decodeRecursive(array &$data)
    {
        foreach ($data as $key => &$value) {
            if (is_array($value)) {
                self::decodeRecursive($value);
                continue;
            }
            if (strpos($key, "id") !== false) {
                if (is_string($value)) {
                    $id = static::decode($value);
                    $data[$key] = $id ?? $value;
                } elseif (is_array($value)) {
                    $data[$key] = static::decodeArray($value);
                }
            }
        }
    }
}
处理请求数据($_POST,$_PUT,$_GET)提交过来的数据

1.新建JsonParser继承Yii自带的JsonParser,代码如下

class JsonParser extends yiiwebJsonParser
{
    /**
     * @inheritDoc
     */
    public function parse($rawBody, $contentType)
    {
        $data = parent::parse($rawBody, $contentType);
        if ($data !== null) {
            HashidsHelper::decodeRecursive($data);
        }
        return $data;
    }
}

2.新建Request集成Yii自带的Request,重写getQueryParams,代码如下:

    public function getQueryParams()
    {
        $data = parent::getQueryParams();
        if ($data !== null) {
            HashidsHelper::decodeRecursive($data);
        }
        return $data;
    }

3.配置web.php的components,更改为我们自定义的处理器

        "request" => [
            "class" => appcomponentsRequest::class,
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            "cookieValidationKey" => "123456",
            "enableCsrfValidation" => false,
            "parsers" => [
                "application/json" => appcomponentswebJsonParser::class
            ]
        ],
处理响应数据

1.新建JsonResponseFormatter继承Yii的JsonResponseFormatter,代码如下:

class JsonResponseFormatter extends yiiwebJsonResponseFormatter
{
    /**
     * @inheritDoc
     */
    public function format($response)
    {
        if ($response->data !== null) {
            HashidsHelper::encodeRecursive($response->data);
        }
        parent::format($response);
    }
}

2.配置web.php的components,替换response组件

        "response" => [
            "class" => appcomponentswebResponse::class,
            "format" => Response::FORMAT_JSON,
            "formatters" => [
                "json" => [
                    "class" => appcomponentswebJsonResponseFormatter::class,
                    "prettyPrint" => YII_DEBUG
                ]
            ]
        ],
测试

1.SiteController添加方法

    public function actionA($corporation_id)
    {
        $data = Yii::$app->request->post();
        var_dump($data, $corporation_id);
    }

    public function actionB()
    {
        return [
            "app_id" => 1,
            "app" => [
                "app_id" => 2
            ]
        ];
    }

2.请求测试,这个加密过的hash读者可能解不开,因为我们用的salt不一样,替换为你自己的即可

POST /site/a?corporation_id=XaYeAV2q80pkB4KL

{
  "corporation_id": "XaYeAV2q80pkB4KL",
  "applet":{
    "id":"XaYeAV2q80pkB4KL",
    "appid":"xxxxxx"
  }
}

3.响应的内容如下:

array(2) {
  ["corporation_id"]=>
  int(1)
  ["applet"]=>
  array(2) {
    ["id"]=>
    int(1)
    ["appid"]=>
    string(6) "xxxxxx"
  }
}
int(1)

4.响应测试

GET /site/b

5.响应内容如下

{
    "app_id": "XaYeAV2q80pkB4KL",
    "app": {
        "app_id": "LOnMp3QR5lryDgRK"
    }
}
写在最后

不知道这个算不算AOP编程?个人觉得算,在业务逻辑之外处理,业务层对外部输入和自身输出是透明的(理解为业务层自己不知道加解密)。

本文核心在于两个递归方法,其他语言类似,像nodejs可以使用中间件来处理。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29086.html

相关文章

  • hashids插件库解决序列id易泄露易推导的问题

    摘要:自增序列类型数字主键,完全的自动增长,容易被判断推导出其他的主键值。本方案就是使用解决易推导的问题,并且在数据量不大的情况下也不大。这些是彼此独立生成的,碰撞风险非常小,可以忽略不计。是可以根据盐值反向解码的。增量输入被破坏以保持不可思议。 ID管理方式的介绍 32位UUID转Base64编码,快速的id生成方案,问题在于编码可读性差,长度太长,查询效率低。 自增序列类型数字主键,完...

    lentrue 评论0 收藏0
  • 优雅的 ID 混淆扩展包 Laravel Hashid

    摘要:整合了等高性能编码算法,并提供了统一的优雅的简单易用的调用接口,将敏感数据混淆编码成可还原的非连续的安全的标识符。重构现有的发码生成机制使用数据库自带的索引主键,但是对外进行混淆。对加密串进一步混淆,并生成安全的字符串。 Laravel Hashid 整合了 [Base62], [Base64], [Hashids], [Optimus] 等高性能编码算法,并提供了统一的、优雅的、简单...

    Cheriselalala 评论0 收藏0
  • 自如2018新年活动系统 — 抢红包

    摘要:活动规模既然公司对自如客这么阔,那对我们员工也得够意思,所以年底我们共准备了个活动。拆分后,红包占有只需操作,响应性能已不是问题。 首发于 樊浩柏科学院 2017 年是自如快速增长的一年,自如客突破 100 万,管理资产达到 50 万间,在年底成功获得了 40 亿 A 轮融资,而这些都要感谢广大的自如客,公司为了回馈自如客,在六周年活动时就发放了 6000 万租住基金,当然年底散币活...

    fanux 评论0 收藏0
  • 自如2018新年活动系统 — 抢红包

    摘要:活动规模既然公司对自如客这么阔,那对我们员工也得够意思,所以年底我们共准备了个活动。拆分后,红包占有只需操作,响应性能已不是问题。 首发于 樊浩柏科学院 2017 年是自如快速增长的一年,自如客突破 100 万,管理资产达到 50 万间,在年底成功获得了 40 亿 A 轮融资,而这些都要感谢广大的自如客,公司为了回馈自如客,在六周年活动时就发放了 6000 万租住基金,当然年底散币活...

    learning 评论0 收藏0
  • 一个 PHP 扩展: 根据数字生成唯一的字符串 ID

    摘要:是一个可以生成唯一的非顺序的字符串号码,它还可以对这些进行解密,你可以利用它来加密你不想暴露给用户的数字。安装你可以设置一些选项在里,或者你也可以在构造方法里面设置,但是我推荐你在中设置,这样你可以拥有更好的性能。 Hashids 是一个可以生成唯一的非顺序的字符串 ID 号码,它还可以对这些 ID 进行解密,你可以利用它来加密你不想暴露给用户的数字 ID。 安装 $ git clon...

    G9YH 评论0 收藏0

发表评论

0条评论

jk_v1

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<