生成私有,唯一,安全的URL

时间:2009-03-01 09:15:31

标签: php security url

我想生成一个安全的一键访问类型的网址,类似于下面的示例。我将使用PHP但这是无关紧要的,因为我只是想了解基本概念。一些答案建议使用GUID,但我认为这不会给我一个绝对独特,安全的URL,如下所示。

#    Google Calendar
3qq6jlu04ptlhmb9fencsu5t2k
#    Private
3qq6jlu04ptlhmb9fencsu5t2k
#    Private 'token'
163a0afe7fkb1ba2acd04c11ef0eefe8
#    LogMeIn
#    1024 bit - 128 Character URL
72oxuj0fzefqo3fu04xjtvmd0adj2948rfh7g5by4forkwcy7t651z7hcb6kjjgqkxmvmfqpyrcfy15z1fto8ewcxstjc6avicag7d5qnoimsm19kb9kgi9i7v6z01d5

我倾向于128字符,1024位样式,因为它看起来非常安全。我想我可以制作四个MD5哈希并合并它们,但这真的很有效吗?

对于这样的网址,我有两个特定的意图,但我确信还有其他人可能觉得这很有用。

1)即时登录用户的快捷方式/图标

2)一次性网址(密码恢复链接)

7 个答案:

答案 0 :(得分:9)

更新

对于像单次使用URL这样的东西,我会使用已建议的GUID-esque appoach。确保链接的使用寿命很短。

对于即时登录,没有真正安全的方法来拥有单个URL。

是的,你可以生成一个几乎无法猜测的网址,但这并不能给你带来超级安全性。如果您想记住用户,为什么不使用加密的身份验证cookie?

您提供的示例,Google日历不会仅通过网址登录您,您必须先在网址显示之前进行身份验证。

E.g。点击我的Gmail上的谷歌日历给我:

https://www.google.com/calendar/render?tab=mc&gsessionid=-LTeHrnKoeAbDcVaN68NHA

除非您第一次以我身份验证,否则这无法帮助您访问我的帐户。

旧帖子:

您可以使用com_create _guid在PHP中生成GUID并使用它。

在linux上我认为您可以使用uuid_createhere中的此代码:

<?php
 function guid(){
 if (function_exists('com_create_guid')){
       return com_create_guid();
   }else{
       mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
       $charid = strtoupper(md5(uniqid(rand(), true)));
       $hyphen = chr(45);// "-"
       $uuid = chr(123)// "{"
               .substr($charid, 0, 8).$hyphen
               .substr($charid, 8, 4).$hyphen
               .substr($charid,12, 4).$hyphen
               .substr($charid,16, 4).$hyphen
               .substr($charid,20,12)
               .chr(125);// "}"
       return $uuid;
   }
}
echo guid();
?>

答案 1 :(得分:9)

尝试uniqid - 并且可能与md5哈希相结合,如示例中所示:

// no prefix
// works only in PHP 5 and later versions
$token = md5(uniqid());

// better, difficult to guess
$better_token = md5(uniqid(rand(), true));

但我必须注意,没有以这种方式生成的网址(无论哈希算法是什么)都是“安全的”,很难猜测。

答案 2 :(得分:4)

只需生成一个GUID。虽然这不是旧式的顺序GUID,但这很重要。

然而,似乎php没有自己的GUID生成功能。另一个答案中建议的com_create_guid函数似乎只能在Windows上运行时才能在php中使用。

在手册页上为非Windows提供了com_create_guid的用户建议替代方法:

function guid(){
    if (function_exists('com_create_guid')){
        return com_create_guid();
    }else{
        mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
        $charid = strtoupper(md5(uniqid(rand(), true)));
        $hyphen = chr(45);// "-"
        $uuid = chr(123)// "{"
                .substr($charid, 0, 8).$hyphen
                .substr($charid, 8, 4).$hyphen
                .substr($charid,12, 4).$hyphen
                .substr($charid,16, 4).$hyphen
                .substr($charid,20,12)
                .chr(125);// "}"
        return $uuid;
    }
}

但我必须承认,我不愿意将它用于任何重要的事情,以防潜伏在我身上的非加密训练的头脑没有发现。

答案 3 :(得分:3)

id无法猜测,GUID是独一无二的,但并不难猜测。

你需要一个好的随机数生成器,每个加密/加密库至少有一个,我不懂PHP,所以我不能给你这个函数名。

然后你必须决定你的随机数会有多长,你应该选择一个如此之大的长度,以至于任何猜测数字的人都会得到一个未分配的数字 - 或者:

  1. 估算您必须生成的唯一网址数量,计算需要多少位来代表它们,然后将位数加倍(至少)。

  2. 或者,使用您的用户将接受的最大数量

  3. 现在您有一个“安全”号码,您可以将其转换为十进制,十六进制或base64并使用该字符串。

答案 4 :(得分:2)

我会避免这个:

  

1)即时登录用户的快捷方式/图标

因为这些URL可以缓存/登录代理,网络日志,浏览器缓存,书签,电子邮件等。

答案 5 :(得分:1)

修剪额外的花括号

$ guid = strtolower(trim(com_create_guid(),“{}”)); (PHP 5或更高版本)

答案 6 :(得分:1)

如果您想确保该URL既是唯一的,又只能使用有限次数:

  • 使用以下字段保留一个小型数据库:RandomKeyInternalURLCounterTimeStamp

  • 从足够大的池中创建一个随机数 非顺序GUID应该足够了

  • 将其作为RandomKey保存在您的数据库中,以及系统处理该URL和时间戳所需的实际内部URL或资源代码。

  • 当用户点击或输入网址时,请针对该数据库进行检查:如果TimeStamp太旧或Counter太高,请采取适当的措施(例如,如果您希望此URL可在有限时间或特定次数内访问。) 否则,只需使用InternalURL处理请求,然后将结果发回给用户。

  • 当URL已被使用或已达到其最大使用计数器时,只需将其从数据库中删除,以便不再使用它。

很高兴为您提供几乎无法猜到的一次性网址。

当然,您还必须实施一些安全检查,以限制人们尝试访问无效网址的速度。