我正在编写一个脚本,它基本上允许我在单个get请求的查询字符串中发送一个URL和两个整数维度。我正在使用base64对它进行编码,但它很长,而且我担心URL可能会变得太大。
有没有人知道另一种更短的方法呢?在get请求中收到它时需要可解码,所以md5 / sha1是不可能的。
感谢您的时间。
编辑:抱歉 - 我应该更好地解释一下:好的,在我们的网站上,我们会显示已发布以供审核的网站的屏幕截图。我们有自己的缩略图/截图服务器。我基本上将使图像标记包含一个编码字符串,该字符串存储用于截取屏幕截图的URL,以及要显示的图像的宽度/高度。然而,我不想在“原始文本”中让世界看到它。显然,base64可以由任何人决定,但我们不希望你的普通乔获取URL路径。我真的需要在一个GET请求中获取:url,width,height。
答案 0 :(得分:5)
由于您只使用base64对字符串进行模糊处理,因此您可以使用其他内容对其进行模糊处理,例如rot13(或您自己的简单字母替换函数)。因此,urlencode(str_rot13($str))
要编码,str_rot13(urldecode($str))
要解码。
或者,为了只使用较短的base64编码字符串,您可以在base64编码之前压缩字符串:base64_encode(gzencode($str, 9))
和gzdecode(base64_decode($str))
进行解码。
或者,如果这主要是一个安全问题(你不介意人们看到这个URL,你只是想让人们不去攻击它)你可以用普通的查询字符串变量传递这些参数,但是附加一个哈希来防止篡改。即:
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实际上是执行一个动作,比如转到另一个站点,制作和存储屏幕截图,然后就是POST。正如他们的名字所示,GET用于检索; POST用于提交数据。如果你要在昂贵的操作上使用GET制作屏幕截图时,您可能会在Google等索引这些网址时最终管理您自己的网站。)
答案 1 :(得分:3)
URL并不意味着发送长串数据,编码或未编码。在某一点之后,当您处理通过URL发送的大量数据时,您应该开始使用POST或某种形式的本地存储。仅供参考,IE的URL限制为2038个字符。
修改强> 我不明白一件事。你为什么不缓存屏幕截图?每当有人查看带有该URL的IMG链接的页面时,必须采用新的屏幕截图,这似乎非常耗费资源。
也许您的受众群体很小,资源也不是问题。但是,如果它是相反的,实际上它是一个公共网站 - 它不会很好地扩展。我知道我的内容超出了您原来提出的问题,但这将解决您的问题以及更多问题。
只要网站发布,就将网址存储在某种本地存储中,最好是在sql中存储。我将继续这个示例,就像您选择SQL一样,但当然您的实现是您的选择。我将有一个主键,url字段和last_updated时间戳,以及可选的图像缩略图路径。
通过利用本地存储,您现在可以在每次请求包含缩略图的页面时从本地存储在服务器上的缓存副本中提取图像。节省了大量资源,并且由于这些网站可能不会经常更新,因此您可以拥有一个cron作业或运行每x个时间的脚本来刷新整个数据库中的屏幕截图。现在,您所要做的就是直接链接(这取决于您的实现)到图像,并且这些巨大的网址字符串都不会发生。
或者,只需采取简单的方法,并使用http://www.snap.com/
进行客户端操作答案 2 :(得分:2)
听起来你的目标是1. 在视觉上模糊了网址,以及2.通常紧凑地编码数据以便在网址中使用。
首先,我们需要隐藏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指定自己的参数。为此,您将使用HMAC,并对Base64进行Base64URL编码。您还可以保留哈希的子字符串(每个字符约6位)以节省空间。 sign()
(下面)添加一个8字符的MAC(6位/ char的48位散列):
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
更新:更好RotURL function。
答案 3 :(得分:1)
不要base64_encode($whole_file)
。以块的形式发送内容并编码块。此外,如果你必须知道在调用base64_encode()
后你的数据块有多大,它的大小会增加一倍以上(但小于2.1*strlen($chunk)
)
答案 4 :(得分:1)
假设我理解正确,你仍然可以使用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>
答案 5 :(得分:0)
生成在不同服务器上运行的URL的脚本是否与解释它们的脚本不同?如果它们位于同一台服务器上,显而易见的方法是将目标URL,宽度和高度存储在数据库中,并简单地在查询字符串中传递随机生成的记录标识符。