dsentker/url-fingerprint 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

dsentker/url-fingerprint

Composer 安装命令:

composer require dsentker/url-fingerprint

包简介

Build a hash from a url

README 文档

README

A library that creates a unique hash value from a URL - without getting a headache.

This library aims to get a unique but consistent digest (hash result) from a URL with or without side effects. It generates equal hash results even if the parameter order in the query string is different or the URL contains encoded characters like %20.

This library uses the concept of a "Fingerprint". Depending on your settings, a specific fingerprint is generated for each URL, which contains the digest, the hash algorithm and the hashed parts of the URL.

Basic Usage

$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

Installation & Usage

Composer 2 and PHP >= 7.4 is required.

Install url-fingerprint with composer.

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'));

Options

Configure options in the constructor to specify the way the digest is created:

Option Type Default Description
secret string (required!) Choose a secret key for the hash_hmacfunction.
hash_algo string sha256 A hashing algorithm suitable for hash_hmac().
ignore_scheme boolean false Whether to hash the scheme part of the url (https://, ftp:// etc.)
ignore_userinfo boolean false Whether to hash the user information part of the url (e.g. userinfo@host)
ignore_host boolean false Whether to hash the host name or not
ignore_port boolean false Whether to hash the port
ignore_path boolean false Whether to path of the URL (e.g. /foo/index.php)
ignore_query boolean false Whether to hash the query string parts in the URL (Keys and values).
ignore_fragment boolean false Whether to hash the fragment / hash suffix in the URL or not.

Examples

$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

Testing

With PHPUnit: $ ./vendor/bin/phpunit tests

Contributing

If you notice bugs, have general questions or want to implement a feature, you are welcome to collaborate.

Please see CONTRIBUTING for details.

Background

Motivation

Generating a unique hash from a URL is useful, e.g. when caching API responses or for security purposes. The simple idea of just hashing the URL can turn into a difficult task. Consider the following example:

$urlHash = hash('md5', 'https://example.com/index.php?foo=bar&qux');

This creates the same hash value (digest) each time. But what if the order of the query string parameters is changed?

$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 :-(

Both URLs are technically the same, but the generated digest is different.

There are more parts of a URL that you may not want to include for the hash algorithm:

$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

All three URLs could be similar according to your requirements and should therefore generate the same hash result. This is what this library was built for. There are other things in a URL that shouldn't affect the hash value of a URL:

  • The order of the query parameters is different
  • Another protocol is used
  • URL-encoded characters such as %20 should be taken into account

Predecessor

This library replaces the predecessor, the url-signature library.

Compared to the url-signature library, this library is rewritten completely and should solve the following drawbacks:

  • The url-signature library did not follow the Single-responsibility principle
  • Arrays in query string could lead to unexpected results
  • I do not like setting options with bitmask flags
  • A thin wrapper for normalizing query strings is not required
  • Insufficient investigation possibilities to debug the hash process

dsentker/url-fingerprint 适用场景与选型建议

dsentker/url-fingerprint 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 335 次下载、GitHub Stars 达 1, 最近一次更新时间为 2021 年 07 月 16 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「http」 「url」 「https」 「uri」 「hostname」 「rfc3986」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 dsentker/url-fingerprint 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 dsentker/url-fingerprint 我们能提供哪些服务?
定制开发 / 二次开发

基于 dsentker/url-fingerprint 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 335
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 14
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-2.0-or-later
  • 更新时间: 2021-07-16