dsentker / url-fingerprint
从URL构建哈希值
0.4.0
2021-08-03 11:07 UTC
Requires
- php: >=7.4
- ext-json: *
- ext-mbstring: *
- league/uri: ^6.0
- league/uri-components: ^2.3
- symfony/options-resolver: ^5.3
Requires (Dev)
- phpunit/phpunit: ^8.0 || ^9.0
README
一个从URL创建唯一哈希值的库 - 而不会让你头疼。
此库旨在从URL获取唯一但一致的摘要(哈希结果),无论是否有副作用。即使在查询字符串中的参数顺序不同或URL包含如%20
之类的编码字符,它也会生成相同的哈希结果。
此库使用“指纹”的概念。根据您的设置,为每个URL生成一个特定的指纹,其中包含摘要、哈希算法和URL的哈希部分。
基本用法
$reader = new FingerprintReader([ 'secret' => 's3cre7v4lu3', ]); $fingerprint1 = $reader->capture('http://www.example.com/info?id=42&details'); // Same URL, but different parameter order in query string. $fingerprint2 = $reader->capture('http://www.example.com/info?details&id=42'); $reader->compare($fingerprint1, $fingerprint2); // bool(true) echo $fingerprint1->digest; // d7335d0a237f47a049415a780c4e1c96 echo $fingerprint2->digest; // d7335d0a237f47a049415a780c4e1c96 - the same
安装与使用
需要Composer 2和PHP >= 7.4。
使用Composer安装url-fingerprint。
composer require dsentker/url-fingerprint
# Create a FingerprintReader instance and provide options in the # constructor (the `secret` parameter is required). $reader = new \UrlFingerprint\FingerprintReader([ 'secret' => '42', 'hash_algo' => 'md5' ]); # Capture a new fingerprint by given URL $fingerprint = $reader->capture('http://www.github.com/'); echo $fingerprint->digest; // the result from the hash process echo $fingerprint->hashAlgo; // md5 echo $fingerprint->gist; // a JSON representation of the url parts # Use the compare method to test against another fingerprint $reader->compare($fingerprint, $reader->capture('http://github.com'));
选项
在构造函数中配置选项以指定摘要的创建方式
示例
$reader = new \UrlFingerprint\FingerprintReader([ 'secret' => 's3cre7v4lu3', 'ignore_host' => false, ]); // Different hosts, but not part of the fingerprint. So both digest values are equal. $fingerprint1 = $reader->capture('http://www.example.com/?foo'); $fingerprint2 = $reader->capture('http://www.example.net/?foo'); $reader->compare($fingerprint1, $fingerprint2); // true
$reader = new \UrlFingerprint\FingerprintReader([ 'secret' => 's3cre7v4lu3', 'ignore_fragment' => true, ]); // Create fingerprints for two equal URLs except the fragment $fingerprint1 = $reader->capture('https://www.example.com/?foo'); $fingerprint2 = $reader->capture('https://www.example.com/?foo#bar'); // Fingerprints are not the same - The fragment part of the URL is taken into account. $reader->compare($fingerprint1, $fingerprint2); // false
// Define query string keys which should be ignored and pass it as 2nd argument in the capture method. $ignoreQuery = ['foo', 'baz']; $fingerprint1 = $reader->capture('https://www.example.com/detail'); $fingerprint2 = $reader->capture('https://www.example.com/detail?foo=bar', $ignoreQuery); // Fingerprints are equal because the 'foo' parameter is ignored $reader->compare($fingerprint1, $fingerprint2); // true
测试
使用PHPUnit: $ ./vendor/bin/phpunit tests
贡献
如果您发现错误,有一般性问题或想实现一个功能,欢迎您合作。
请参阅CONTRIBUTING以获取详细信息。
背景
动机
从URL生成唯一哈希值很有用,例如,当缓存API响应或出于安全目的时。简单地对URL进行哈希处理的想法可能变成一项艰巨的任务。考虑以下示例
$urlHash = hash('md5', 'https://example.com/index.php?foo=bar&qux');
这会创建相同的哈希值(摘要)每次。但如果查询字符串参数的顺序改变呢?
$url1 = 'https://example.com/index.php?foo=bar&qux'; $url2 = 'https://example.com/index.php?qux&foo=bar'; hash_equals( hash('md5', $url1), hash('md5', $url2) ); // false :-(
这两个URL在技术上都是相同的,但生成的摘要不同。
URL中还有更多部分您可能不想包含在哈希算法中
$url = 'https://example.com/#logo'; // Anchor / fragment appended $url = 'http://example.com/'; // Different protocol $url = 'https://example.com/?'; // Empty query string / No key/value groups
根据您的要求,这三个URL可能非常相似,因此应该生成相同的哈希结果。这正是此库的构建目的。在URL中还有其他不应影响URL哈希值的事物
- 查询参数的顺序不同
- 使用另一种协议
- 应考虑URL编码字符,如
%20
前身
此库取代了前身,即url-signature库。
与url-signature库相比,此库已完全重写,并应解决以下缺点
- url-signature库没有遵循单一职责原则
- 查询字符串中的数组可能导致意外结果
- 我不喜欢使用位掩码标志设置选项
- 不需要对查询字符串进行规范的薄包装器
- 调试哈希过程的研究可能性不足