php - 414 URI 太长。但不总是

标签 php apache amazon-ec2 virtualhost apache2.4

我有以下 url 来重设我的密码:

http://example.com/resetPassword/LtoyURJd5AYuP3KEGg4gx8fvUprT37LBQDlvhg22qjg=.eyJ0b2tlbiI6IiQyeSQxMCRMTlgzU29HdEdOaExsay5yQ1puQ2ZlZ1wvbVNcL09BMDV2SjhcL1wvcHNRNjZaQmRpbWpOdnhGQlciLCJ0aW1lIjoiMjAxNS0xMi0xMVQwOTozOToyOSswMTAwIiwiZW1haWwiOiJsb3JlbS51dC5hbGlxdWFtQGZldWdpYXRwbGFjZXJhdHZlbGl0Lm9yZyJ9

在本地开发机器上运行没有任何问题。但是在公共(public)服务器(托管在亚马逊 ec2 上)上,我得到一个 414 Uri 太长了。我试图修复它,但我似乎无法解决问题。 ps:我已经将 url 替换为 example.com

我尝试将以下行添加到/etc/apache2/apache2.conf,vhosts conf。既同时又分开。是的。我也每次都重新启动 apache 服务。

LimitRequestLine 8190

另外,当我请求其他长 url 时也没有问题。例如。我重命名了 robots.txt,这样我就可以请求以下网址:

http://example.com/robotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsr/robotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsroborobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobots.txtrobots.txtrobots.txtrobots.txtrobots.txtrobots.txtrobots.php?test=ok
http://example.com/robotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsr/robotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsroborobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobotsrobots.txtrobots.txtrobots.txtrobots.txtrobots.txtrobots.txtrobots.php
http://example.com/robots.txt?klsadjflkasdjflkdsajflkdsja=sdakjflksadjfoaiwsefnalkfjsdakjflksadjfoaiwsefnalkfjsdakjflksadjfoaiwsefnalkfjsdakjflksadjfoaiwsefnalkfjsdakjflksadjfoaiwsefnalkfjsdakjflksadjfoaiwsefnalkfjsdakjflksadjfoaiwsefnalkfj

我还把robots.txt 移到其他位置,并为它制定了重写规则。即便如此,它似乎也能正常工作。所以 mod_rewrite 似乎不是问题所在。

当 url 的长度达到 +/- 275 个字符时,就会出现问题。它与 273 的重置链接一起工作,较长的是 324 个字符。我认为机器人的长 URL 大约有 400 个字符。

我似乎也遇到了我的虚拟主机未正确加载的问题(我不确定是否相关)。服务器总是重定向到默认定义的路径。不是虚拟主机。 apache2ctl -s 输出给出以下内容:

ubuntu@ip-172-31-28-19:~$ apache2ctl -S                                                                                                                                                                                                                                                               
VirtualHost configuration:
<ip>:80        example.com (/etc/apache2/apache2.conf:228)
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www/public"
Main ErrorLog: "/var/log/apache2/error.log"
Mutex proxy: using_defaults
Mutex default: dir="/var/lock/apache2" mechanism=fcntl 
Mutex mpm-accept: using_defaults
Mutex watchdog-callback: using_defaults
Mutex rewrite-map: using_defaults
PidFile: "/var/run/apache2/apache2.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="www-data" id=33 not_used
Group: name="www-data" id=33 not_used

更新 2015-12-18 在与我团队中的其他开发人员的讨论中,我们将为亚马逊上的该服务器选择不同的基础镜像。似乎还有比这更多的问题。所以这个问题已经过时了。

最佳答案

不用base64_encode()重设密码所需的信息,所有信息都在那里供每个人base64_decode()使用,请看这个:

// this is from your example
$encoded = 'eyJ0b2tlbiI6IiQyeSQxMCRMTlgzU29HdEdOaExsay5yQ1puQ2ZlZ1wvbVNcL09BMDV2SjhcL1wvcHNRNjZaQmRpbWpOdnhGQlciLCJ0aW1lIjoiMjAxNS0xMi0xMVQwOTozOToyOSswMTAwIiwiZW1haWwiOiJsb3JlbS51dC5hbGlxdWFtQGZldWdpYXRwbGFjZXJhdHZlbGl0Lm9yZyJ9';

$data = json_decode(
    base64_decode($encoded), 
    true
);

// array (
//     'token' => '$2y$10$LNX3SoGtGNhLlk.rCZnCfeg/mS/OA05vJ8//psQ66ZBdimjNvxFBW',
//     'time' => '2015-12-11T09:39:29+0100',
//     'email' => 'lorem.ut.aliquam@feugiatplaceratvelit.org',
// )

将数据保存在表中

如何改为持久化该数据 - 无论是在数据库中还是其他具有有限生命周期的地方 - 然后使用 UUID 或使用上述数据创建的哈希作为密码重置的标识符?

CREATE TABLE `password_reset` (
  `id` char(40) NOT NULL DEFAULT '',
  `token` char(60) NOT NULL DEFAULT '',
  `time` datetime NOT NULL,
  `email` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

来自 SHA-1 的标识符

然后生成你的标识符:

$id = sha1(serialize([
    'token' => '$2y$10$LNX3SoGtGNhLlk.rCZnCfeg/mS/OA05vJ8//psQ66ZBdimjNvxFBW',
    'time' => '2015-12-11T09:39:29+0100',
    'email' => 'lorem.ut.aliquam@feugiatplaceratvelit.org',
    'foo' => microtime(), // for some variation
]);

将数据存储在您的表中,那里有您的固定长度标识符,您的密码重置 URL 变为

http://example.com/resetPassword/0f4d2541c25ba8edbb3cd6df362d7dbf6317d7a5

作为 UUID 的标识符

与其使用 sha1() 从某些输入创建散列,不如使用,例如 ramsey/uuid 可能更好。生成基于时间的 UUID(固定长度,36 个字符):

use Ramsey\Uuid\Uuid;

$id = Uuid::uuid1()->toString()

虽然这不能解决您允许超长 URI 的问题,但它以一种更好、更安全的方式解决了这个问题。

奖金

看看 OWASP 的 Forgot Password Cheatsheet和相关的,也许它有助于使您的应用程序更安全!

关于php - 414 URI 太长。但不总是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34268099/

相关文章:

php - 成功消息显示在错误的页面上

php - Apache 或 PHP 将 HTTP header 添加到 CSS 和 JS 文件

java - 发出类似 "mvn install"的命令时出现错误

java - 多个 Tomcat 8 安装或虚拟主机

amazon-ec2 - Amazon EC2 私有(private) key (.pem) 和 secret 访问 key 之间有什么区别?

php - 将存储的日期值与计算机的当前日期进行比较

c# - 在发送到服务器之前更改 Webbrowser 发布表单

php - 在 URL 中使用 & 符号

python - Apache/WSGI 进程死亡

ssh - 无法从 LAN 通过 SSH 访问我的 Amazon EC2 实例,我认为该实例阻塞了端口 22