Javascript 如何使此登录/重定向方法更安全

Javascript 如何使此登录/重定向方法更安全,javascript,php,security,Javascript,Php,Security,我有一个向用户发送电子邮件的应用程序,每个电子邮件都包含一个指向用户必须访问的页面的链接 链接是唯一id+随机数的md5 该链接看起来像:www.domain.com/index.php?id\u page= 在索引页面上,我将$\u GET[“id\u page”]保存在会话变量中,$\u session[“id\u page”]并将用户重定向到他必须看到的页面(仅当链接包含id\u page时,用户才会重定向到该页面) 如何改进此方法并使其更安全?我如何保证用户进入指定给他们的页面,而不能进

我有一个向用户发送电子邮件的应用程序,每个电子邮件都包含一个指向用户必须访问的页面的链接

链接是唯一id+随机数的md5

该链接看起来像:
www.domain.com/index.php?id\u page=

在索引页面上,我将
$\u GET[“id\u page”]
保存在会话变量中,
$\u session[“id\u page”]
并将用户重定向到他必须看到的页面(仅当链接包含
id\u page
时,用户才会重定向到该页面)


如何改进此方法并使其更安全?我如何保证用户进入指定给他们的页面,而不能进入任何其他页面?

您可以在URL中添加他们的电子邮件。有人猜测其他人的电子邮件和相关哈希的概率大约为0。

这里您关心的是时间问题,而不是安全问题:)。如果您允许任何人猜测无限多个id_页面值,那么在足够的时间内,最终会有人发现一个随机的有效id_页面值

您唯一的real防御措施是增加散列的长度,使其(平均)在随机有效id_页面上发生的时间更长(以月或年为顺序)。这可以通过使用sha256或sha512而不是md5来实现

另一种方法是,如果某人(例如)在id_页面值上连续3次出现错误猜测,则将其锁定一段时间。这将大大减少他们在给定时间段内可以尝试的值的数量


最后,如果用户在重定向时已经登录,那么还可以将生成的哈希存储在数据库表中。这样,您可以将特定哈希映射到表中的一个且仅一个用户标识。如果用户试图访问他们在数据库中不对应的散列页,则可以将其重定向到其他位置。

一种可以很好地防止猜测ID号的方法是向ID添加某种填充,然后将其转换为base32。当然,这并不能完全消除猜测身份证的能力,但对于四处窥探的人来说,这确实会让猜测身份证的时间稍微多一些

如果您的URL为www.domain.com/index.php?id_page=1,则可以将该id转换为应用程序中唯一的id,例如:

填充id=id x 9-2

7 = 1 x 9 - 2
16 = 2 x 9 -2
25 = 3 x 9 - 2
然后,您可以将新的填充ID转换为base 32,即

7 = G4
16 = GE3A
25 = GI2Q
然后,新url将是(id为1):

www.domain.com/index.php?id_page=G4

使用此方法,如果有人猜测1-6的基数32,它将返回404,因为您的ID 1实际上被填充为7。猜测8-15不会返回解析的ID,因为下一个ID 2被填充为16,依此类推

这不仅使查询字符串保持较小的大小,而且它也不使用明显的MD5哈希,可以很容易地使用字典按顺序浏览

如果您希望页面链接到特定用户,那么没有理由不能向新的padded_id添加更多值(让我们称之为散列)

例如,如果您有一个ID为12的用户,并且您只希望该用户能够访问ID为10的页面,则需要创建一个包含以下两个值的哈希:

页面id(10)-用户id(12),使用上述示例,这将产生:

(10 x 9 - 2) (12 x 9 - 2)
88-106
HA4A-GEYDM

现在您有了一个很好的小散列链接,可以将其保护到单个用户ID。上面示例中的填充方法非常简单,但它为您提供了解决该问题的总体思路。

不要费心散列或创建唯一ID或其他任何东西。复杂性对你没有帮助

相反,只需生成一个随机令牌,并使用它。256位随机令牌应该足以满足您需要执行的任何操作

因此,使用
mcrypt
(核心扩展):

这将为您提供一个包含256位随机熵的字母表
a-zA-Z0-9-
的44个字符的结果

没有必要对结果或任何东西进行哈希运算。随机数据就足够了

要理解原因,你需要理解

基本上,对于256位随机值,要使2个令牌发生冲突的概率为1%,您需要生成4.8e37令牌(即48个,后面是36个0)

要获得10e-18的碰撞机会(通常被认为是安全的),您需要生成4.8e29令牌

由于这些数字远远超过你所能产生的数字,2个代币发生碰撞的可能性是无穷小的

另一个问题是人们猜测代币。嗯,
MCRYPT\u DEV\u uradom
使用底层操作系统的随机池。这意味着人们猜测您的“唯一id和随机数”的可能性要比猜测此处生成的令牌的可能性大得多


因此,简而言之,只需使用一个随机令牌并完成:-)

他们是在查看该页面时登录的吗?您特别担心哪种利用/规避行为?@ambe5960是的,登录过程在他们重定向到相应页面之前进行。该过程类似于:登录->验证链接是否包含id\u页面->如果它确实将用户重定向到相应的page@Harvtronix我担心一些用户可能会进入其他用户页面,通过找出一个有效的链接,或者通过改变会话变量(我在相应页面上使用的会话变量)来加载内容。
$token = strtr(
    base64_encode(mcrypt_create_iv(256/8, MCRYPT_DEV_URANDOM)), 
    '+/', 
    '-_'
);