繁体   English   中英

POST 数据时是什么导致 mod_security 406 Not Acceptable?

[英]What causes mod_security 406 Not Acceptable when POSTing data?

我的网站上有一篇文章,其中包含(降价)内容:

 # PHP Proper Class Name Class names in PHP are case insensitve. If you have a class declaration like: ```php class MyWeirdClass {} ``` you can instantiate it with `new myWEIRDclaSS()` or any other variation on the case. In some instances, you may want to know, what is the correct, case-sensitive class name. ### Example Use case For example, in one of my libraries under construction [API Doccer](https://github.com/ReedOverflow/PHP-API-Doccer), I can view documentation for a class at url `/doc/class/My-Namespace-Clazzy/` and if you enter the wrong case, like `/doc/class/my-NAMESPACE-CLAzzy`, it should automatically redirect to the proper-cased class. To do this, I use the reflection method below as it is FAR more performant than the `get_delcared_classes` method ## Reflection - get proper case Credit goes to [l00k on StackOverflow](https://stackoverflow.com/a/35222911/802469) ```php $className = 'My\\caseINAccuRATE\\CLassNamE'; $reflection = new ReflectionClass($className); echo $reflection->getName(); ``` results in `My\\CaseInaccurate\\ClassName`; Running the benchmark (see below) on localhost on my laptop, getting the proper case class name of 500 classes took about 0.015 seconds, as opposed to ~0.050 seconds using the `get_declared_classes` method below. ## get_declared_classes - get proper case This was my idea, as I hadn't even considered using reflection, until I saw [l00k's answer on StackOverflow](https://stackoverflow.com/a/35222911/802469). Guessing it would be less efficient, I wrote the code and figured it out anyway, because it's fun! ```php $wrongCaseName = 'Some\\classy\\THIng'; class_exists($wrongCaseName); //so it gets autoloaded if not already done $classes = get_declared_classes(); $map = array_combine(array_map('strtolower',$classes),$classes); $proper = $map[strtolower($wrongCaseName)]; ``` results in `$proper = 'Some\\Classy\\Thing'`; Running the bencmark (see below) on localhost on my laptop, getting the proper case class name of 500 classes took about 0.050 seconds, as opposed to ~0.015 seconds with reflection (above). ## Benchmark: I used the following code to do the benchmark, removing the `classes` directory between each run of the benchmark. It's not perfect. At all. But it gets the job done well enough, I think: ```php <?php $times = []; $times['begin'] = microtime(TRUE); spl_autoload_register(function($className){ if (file_exists($name=__DIR__.'/classes/'.strtolower($className).'.php')){ include($name); } }); if (is_dir(__DIR__.'/classes'))return; mkdir(__DIR__.'/classes'); function generateRandomString($length = 10) { $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; } $times['start_file_write'] = microtime(TRUE); $names = []; for ($i=0;$i<500;$i++){ $className = generateRandomString(10); $file = __DIR__.'/classes/'.strtolower($className).'.php'; if (file_exists($file)){ $i = $i-1; continue; } $code = "<?php \\n\\n".'class '.$className.' {}'."\\n\\n ?>"; file_put_contents($file,$code); $names[] = strtoupper($className); } $times['begin_get_declared_classes_benchmark'] = microtime(TRUE); $propers = []; // foreach($names as $index => $name){ // $wrongCaseName = strtoupper($name); // class_exists($wrongCaseName); //so it gets autoloaded if not already done // $classes = get_declared_classes(); // $map = array_combine(array_map('strtolower',$classes),$classes); // $proper = $map[strtolower($wrongCaseName)]; // if ($index%20===0){ // $times['intermediate_bench_'.$index] = microtime(TRUE); // } // $propers[] = $proper; // } // the above commented lines are the get_declared_classes() method. // the foreach below is for reflection. foreach ($names as $index => $name){ $className = strtoupper($name); $reflection = new ReflectionClass($className); if ($index%20===0){ $times['intermediate_bench_'.$index] = microtime(TRUE); } $propers[] = $reflection->getName(); } $times['end_get_declared_classes_benchmark'] = microtime(TRUE); $start = $times['begin']; $bench = $times['begin_get_declared_classes_benchmark']; $lastTime = 0; foreach($times as $key => $time){ echo "\\nTime since begin:".($time-$start); echo "\\nTime since last: ".($time-$lastTime)." key was {$key}"; echo "\\nTime since bench start: ".($time - $bench); $lastTime = $time; } print_r($times); print_r($propers); exit; ``` ### Results ``` // get_declared_classes method //Time since bench start: 0.052499055862427 is total time for processing get_declared_classes w/ $i=500 //Time since bench start: 0.047168016433716 // last bench time Time since begin:0.062150955200195 // 100 intermediate bench: Time since bench start: 0.0063230991363525 // 200 : Time since bench start: 0.015070915222168 // 300 intermediate bench: Time since bench start: 0.02455997467041 // 400 intermediate bench: Time since bench start: 0.033944129943848 // 480 : Time since bench start: 0.044310092926025 //reflection method: //Time since bench start: 0.01493501663208 //Time since bench start: 0.017416954040527 // 100 intermediate: Time since bench start: 0.0035450458526611 // 200 intermediate: Time since bench start: 0.0066778659820557 // 300 intermediate: Time since bench start: 0.010055065155029 // 400 intermediate: Time since bench start: 0.014182090759277 // 480 intermediate: Time since bench start: 0.01679801940918 ``` #### Results' notes - "Time since bench start" is the entire time it took to run all the iterations. I share this twice above. - "100 Intermediate" (200, 300, etc) are actually the results at 120, 220, etc... I messed up in copy+pasting results & didn't want to do it again. Yes. I'm lazy :) - The results would of course vary between runs of the code, but it's pretty clear that the reflection option is significantly faster. - All was run on a localhost server on an Acer laptop. - PHP Version 7.2.19-0ubuntu0.19.04.1 (from `php info()`)

如上所示,我能够提交文章,一切都按预期工作 - 保存到数据库和一切。 最后一行,如果我将php info()更改为phpinfo() (删除空格),我会收到此错误:

不能接受的!

在此服务器上找不到所请求资源的适当表示。 此错误是由 Mod_Security 生成的。


当我尝试使用phpinfo() (无空格)提交时,我的 PHP 根本不执行,我只收到此错误。 firefox 中的网络选项卡显示状态代码为“406 Not Acceptable”。 $_SERVER['DOCUMENT_ROOT'].'/error_log'错误日志中没有写入任何内容,无论如何,所有 PHP 错误都记录到该日志中。 在我的主文件夹中,有一个logs文件夹,但它仍然是空的。 /etc//etc/my_website_name.com也没有日志。

什么可能导致这个问题? 我可以更改 PHP.ini 中的某些内容吗? .htaccess 会影响这个吗?

至少,我该如何解决这个问题?

故障排除

  • 我可以提交一篇正文中仅包含- PHP 版本 7.2.19-0ubuntu0.19.04.1(来自`phpinfo()`)的文章。
  • 如果我删除 phpinfo() 并向帖子正文添加更多内容(提交的总数据更多),它就可以工作
  • 放置一个空格,如php info()使其工作,并且是当前帖子的存在方式。
  • 我不知道还能做什么

我现在正在使用Simple MDE ,但在我开始使用 Simple MDE 之前,它发生在其他多个场合。 只有相对较大的帖子也包含代码。

我与 HostGator 共享主机,使用 HTTPS:// 和 PHP 7.2.19

我联系了HostGator。 他们在白名单中添加了一些内容,但没有告诉我私密的细节。 它解决了这个问题。

第一个代理花了一段时间,未能解决问题,并提前断开连接。

第二个代理合理地提示并解决了问题,他说我不应该在包含代码的类似类型的 POST 请求中遇到这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM