414 URI太长了。但不总是

时间:2015-12-14 13:19:26

标签: php apache amazon-ec2 virtualhost apache2.4

我有以下网址重置密码:

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

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

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

LimitRequestLine 8190

此外,当我请求其他长网址时,没有问题。例如。我重命名为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不会成为问题所在。

当网址变长+/- 275个字符时,会出现问题。它使用273的重置链接,更长的是324个字符。我认为机器人长的网址是400个字符。

我似乎也遇到了问题(我不是很害羞或不相关)我的vhosts没有正确加载。服务器始终重定向到默认路由中定义的路径。不是vhosts。 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 在与我的团队中的其他开发人员讨论时,我们将在亚马逊上为此服务器选择不同的基本映像。似乎有比这更多的问题。所以这个问题已经过时了。

4 个答案:

答案 0 :(得分:4)

不是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及相关内容,也许有助于提高应用程序的安全性!

答案 1 :(得分:1)

使用POST方法代替get,它将解决您的问题。

但如果您仍想使用&#34; GET&#34;方法而不是&#34; POST&#34;方法,然后在Apache下,如果您想支持更长的请求URI,public class ThreadDemo { public static void main(String args[]) { // This is the first block of code Thread thread = new Thread() { public void run() { for (int i = 0; i < 10; i += 2) { System.out.println("hello this is thread one"); } } }; // This is the second block of code Thread threadTwo = new Thread() { public void run() { for (int i = 0; i < 10; i += 2) { System.out.println("hello this is thread two"); } } }; // These two statements are in the main method and begin the two // threads. // This is the third block of code thread.start(); // This is the fourth block of code threadTwo.start(); } } 的值可以更改为大于其默认值8190的值。

如果您无法在apache配置文件中找到LimitRequestLine,只需在您喜欢的任何地方添加该行。例如:LimitRequestLine

但请注意,如果你真的遇到这个限制,你可能会开始滥用GET。您应该使用POST来传输此类数据 - 特别是因为您甚至承认您正在使用它来更新值

答案 2 :(得分:0)

至少有2个配置变量可能导致414错误。

LimitRequestLine 指令允许服务器管理员设置客户端HTTP请求行的允许大小限制。默认情况下是4094。

LimitRequestFieldSize 指令允许服务器管理员设置HTTP请求标头字段的允许大小限制。默认情况下,它是4094字节

尝试增加它们或尝试查看服务器的请求有多大。如果你把你发送给服务器的请求放在这里可能会很有用。

有用的链接:

答案 3 :(得分:0)

即使在更改EC2图像后它也能正常工作,您也不应该使用此模式。

在您的示例中,架构+主机(即http://example.com)长度为18个字节。如果您的实际主机具有相似的长度,则275 char限制可能表示路径上应用了255个字符的限制。

无论是什么原因,RFC 2068建议不要使用更长的URI(尽管规范要求服务器能够处理任何URI长度):

  

服务器应该谨慎依赖于长度超过255字节的URI,因为某些较旧的客户端或代理实现可能无法正确支持这些长度。

因此,您单击的电子邮件客户端很可能通过发出414代码的某些内部代理(例如反网络钓鱼)重定向点击。这就是Zimbra的工作原理。电子邮件客户端的常见做法是减少恶意链接的威胁。在这种情况下,POST无法帮助您,因为您无法从电子邮件客户端发布POST。

所以唯一的解决方案是在服务器端保留重置信息,并让URI指向更短的令牌。