PHP:嵌入在另一个URL中的URL的较短/模糊编码?

PHP:嵌入在另一个URL中的URL的较短/模糊编码?,php,encoding,get,base64,Php,Encoding,Get,Base64,我正在为自己编写一个脚本,它基本上允许我在单个get请求的查询字符串中发送一个URL和两个整数维。我用base64来编码,但它相当长,我担心URL可能会变得太大 有人知道另一种更短的方法吗?它需要在get请求中接收时能够解码,因此md5/sha1是不可能的 谢谢你抽出时间 编辑:抱歉-我应该解释得更清楚:好的,在我们的网站上,我们会显示一些网站的截图,这些网站会被发布以供审查。我们有自己的缩略图/屏幕截图服务器。基本上,我将让图像标签包含一个编码字符串,它存储要截图的URL,以及要显示的图像的

我正在为自己编写一个脚本,它基本上允许我在单个get请求的查询字符串中发送一个URL和两个整数维。我用base64来编码,但它相当长,我担心URL可能会变得太大

有人知道另一种更短的方法吗?它需要在get请求中接收时能够解码,因此md5/sha1是不可能的

谢谢你抽出时间



编辑:抱歉-我应该解释得更清楚:好的,在我们的网站上,我们会显示一些网站的截图,这些网站会被发布以供审查。我们有自己的缩略图/屏幕截图服务器。基本上,我将让图像标签包含一个编码字符串,它存储要截图的URL,以及要显示的图像的宽度/高度。然而,我不想让全世界看到它的“原始文本”。显然,base64可以由任何人决定,但我们不希望你的普通用户选择URL路径。实际上,我需要在一个GET请求中获取:url、宽度、高度。

url并不意味着要发送长字符串数据,不管是编码的还是未编码的。在某一点之后,当您处理通过URL发送的大量数据时,您应该开始使用POST或某种形式的本地存储。仅供参考,IE的URL限制为2038个字符


编辑: 我不明白一件事。你为什么不缓存屏幕截图?每次有人浏览带有指向该url的IMG链接的页面时,都必须拍摄一张新的屏幕截图,这似乎是非常耗费资源的

也许你的受众很小,资源不是问题。然而,如果它是相反的,事实上它是一个公共网站,将不会很好的规模。我知道我已经超越了你最初的问题,但这将解决你的问题,甚至更多

网站发布后,将url存储在某种本地存储中,最好是sql。我将继续这个示例,就像您选择SQL一样,但当然您的实现是您的选择。我将有一个主键、url字段和最后更新的时间戳,以及可选的图像缩略图路径

通过利用本地存储,您现在可以在每次请求带有缩略图的页面时从服务器本地存储的缓存副本中提取图像。节省了大量资源,而且由于这些网站不会经常更新,您可以使用cron作业或脚本,每x时间运行一次,以刷新整个数据库中的屏幕截图。现在,您所要做的就是直接链接(同样取决于您的实现)到图像,而这些巨大的url字符串不会发生


或者,采取简单的方法,在客户端使用只需不
base64\u编码($whole\u file)
。将内容分块发送并对块进行编码。此外,如果您必须知道在调用
base64_encode()
后,您的区块会变得多大,那么它的大小将增加一倍以上(但小于
2.1*strlen($chunk)

如果我正确理解了您的内容,您仍然可以使用POST进行描述,但我可能没有

我猜你在做这样的事情:

<a href="scripturl?w=11&h=100&url=really-long-secret-base64">
  <img src="imgurl">
</a>

相反,你可以这样做:

<form method="POST" action="scripturl">
  <input type="hidden" name="width" value="100">
  <input type="hidden" name="height" value="100">
  <input type="hidden" name="url" value="secret-url-string-here">
  <input type="image" src="imgurl" name="submit">
</form>


生成运行在不同服务器上的URL的脚本是否与解释URL的脚本不同?如果它们在同一台服务器上,最明显的方法是将目标URL、宽度和高度存储在数据库中,然后在查询字符串中传递随机生成的记录标识符。

由于您仅使用base64来混淆字符串,因此您可以使用其他东西混淆它,如rot13(或您自己的简单字母替换函数)。因此,
urlencode(str_rot13($str))
进行编码,
str_rot13(urldecode($str))
进行解码

或者,为了只使用较短的base64编码字符串,可以在base64编码之前压缩该字符串:
base64\u编码(gzencode($str,9))
gzdecode(base64\u解码($str))
进行解码

或者,如果这主要是一个安全问题(您不介意人们看到URL,您只是想防止人们对其进行黑客攻击),您可以使用普通querystring变量传递这些参数,但附加一个哈希以防止篡改。例如:

function getHash($url, $width, $height) {
  $secret = 'abcdefghijklmnopqrstuvwxyz whatever you want etc.';
  return sha1($url . $width . $height . $secret);
}

// So use this hash to to construct your URL querystring:
$hash = getHash($url, $width, $height);
$urlQuerystring = '?url='.urlencode($url).'&width='.(int) $width.
                  '&height='.(int) $height.'&hash='.$hash;

// Then in your code that processes the URL, check the hash first
if ($hash != getHash($url, $width, $height))
  // URL is invalid

(离题:人们说你应该使用POST而不是GET。如果所有这些URL都是从你的数据库中获取屏幕截图来显示(即搜索查找),那么GET是正确的。但是如果调用这些URL实际上是执行一个操作,比如访问另一个站点,制作并存储屏幕截图,那么这就是一篇文章。正如他们的名字所暗示的,GET是用于检索的;POST是用于提交数据的。如果你在制作屏幕截图等昂贵的操作中使用GET,你可能最终会失败当Google等为这些URL编制索引时,您自己的网站。)

听起来您的目标是1.在视觉上模糊URL,2.通常对数据进行压缩编码,以便在URL中使用

首先,我们需要隐藏URL。由于URL使用了Base64字典的大部分内容,因此任何产生二进制(然后必须使用Base64)的编码都可能会增加大小。最好将字典保持在URL安全范围内,在应用
urlencode()
时不需要进行转义。即,您希望:

/**
 * Rot35 for URLs. To avoid increasing size during urlencode(), commonly encoded
 * chars are mapped to more rarely used chars (end of the uppercase alpha).
 *
 * @param string $url
 * @return string
 */
function rotUrl($url) {
    return strtr($url,
        'abcdefghijklmnopqrstuvwxyz0-:/?=&%#123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
        '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0-:/?=&%#');
}
现在,为了保存字节,我们可以将URL模式编码为一个字符(例如,对于HTTP,
h
,对于HTTPS,
h
),并将维度转换为基数32

function obscure($width, $height, $url) {
    $dimensions = base_convert($width, 10, 32) . "."
                . base_convert($height, 10, 32) . ".";
    preg_match('@^(https?)://(.+)@', $url, $m);
    return $dimensions . (($m[1] === 'http') ? 'h' : 'H') . rotUrl($m[2]);
}

function unobscure($str) { /* exercise for the reader! */ }

$url = 'https://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=Base64';
$obs = obscure(550, 300, $url);
// h6.9c.H5E.N9B9G5491.FI7UNU9E45O.G8GVK9KC5W-G5391CYcj-51I38XJ51I38Wk1J5fd
因为我们避免了非URL安全字符,所以如果将其放在查询字符串中(使用
urlencode
),它不会增长太多(在本例中根本不会)

此外,您可能希望对此字符串进行签名,以便知道编码的人仍然无法通过URL指定自己的参数。为此,您可以使用和Base64URL对哈希进行编码。您还可以
function sign($key, $data) {
    return $data . _hmac($key, $data, 8);
}
function verify($key, $signed) {
    $mac = substr($signed, -8);
    $data = substr($signed, 0, -8);
    return $mac === _hmac($key, $data, 8) ? $data : false;
}
function _hmac($key, $data, $macLength) {
    $mac = substr(base64_encode(hash_hmac('sha256', $data, $key, true)), 0, $macLength);
    return strtr($mac, '+/', '-_'); // for URL
}

$key = "Hello World!";
$signed = sign($key, $obs); // appends MAC: "w-jjw2Wm"

$obs = verify($key, $signed); // strips MAC and returns valid data, or FALSE