hashids php 如何使用,使用Hashids来保护你的数据库主键

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

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

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 Hashids\Hashids('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 \Hashids\Hashids('salt',16);

return $hashids->encode($id);

}

public static function decode($hash)

{

$hashids = new \Hashids\Hashids('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 \yii\web\JsonParser

{

/**

* @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' => \app\components\Request::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' => \app\components\web\JsonParser::class

]

],

处理响应数据

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

class JsonResponseFormatter extends \yii\web\JsonResponseFormatter

{

/**

* @inheritDoc

*/

public function format($response)

{

if ($response->data !== null) {

HashidsHelper::encodeRecursive($response->data);

}

parent::format($response);

}

}

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

'response' => [

'class' => \app\components\web\Response::class,

'format' => Response::FORMAT_JSON,

'formatters' => [

'json' => [

'class' => \app\components\web\JsonResponseFormatter::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可以使用中间件来处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据库中,是非常重要的概念,用于保证数据表中每一行数据的唯一性。的类型选择应该根据具体应用场景和数据表的特点来确定。以下是几种常见的类型: 1. 自增长整数型:这是最常见的类型,可以使用整数型数据作为,每次插入一条新的数据时,自动将值自增1。这种类型的可以保证数据的唯一性,而且查询速度比较快,因为整数型数据的比较和查找都比较快。例如,在MySQL数据库中,可以使用AUTO_INCREMENT属性来定义自增长整数型。 2. UUID型:UUID(通用唯一识别码)是一种标识符,可以保证在分布式系统中的唯一性。UUID可以保证数据的唯一性,而且不需要依赖数据库自增长机制。这种类型的比较适合分布式系统或者需要保证数据隐私的场景。例如,在Java中,可以使用java.util.UUID类生成UUID。 3. 字符串型:有时候,我们需要使用非数字的类型,比如字符串型。字符串型可以使用任何字符串类型作为,比如GUID、哈希值等。这种类型的可以保证数据的唯一性,而且比较灵活,可以根据具体应用场景来选择具体的字符串类型。例如,在MongoDB数据库中,使用ObjectID作为字符串型。 总的来说,选择类型应该根据具体的应用场景和数据表的特点来确定。在选择类型时,需要考虑数据的唯一性、查询效率、数据类型、数据规模等因素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值