简体   繁体   English

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

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

I have an article on my website with the (markdown) content:我的网站上有一篇文章,其中包含(降价)内容:

 # 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()`)

As shown above, I'm able to submit the article & everything works as expected - saves to DB & everything.如上所示,我能够提交文章,一切都按预期工作 - 保存到数据库和一切。 The very last line, if I change php info() to phpinfo() (removing the space), I get this error:最后一行,如果我将php info()更改为phpinfo() (删除空格),我会收到此错误:

Not Acceptable!不能接受的!

An appropriate representation of the requested resource could not be found on this server.在此服务器上找不到所请求资源的适当表示。 This error was generated by Mod_Security.此错误是由 Mod_Security 生成的。


When I try to submit with phpinfo() (no space), my PHP does not execute at all and I only get this error.当我尝试使用phpinfo() (无空格)提交时,我的 PHP 根本不执行,我只收到此错误。 The network tab in firefox shows "406 Not Acceptable" for the status code. firefox 中的网络选项卡显示状态代码为“406 Not Acceptable”。 Nothing is being written to my error log in $_SERVER['DOCUMENT_ROOT'].'/error_log' , which is where all the PHP errors log to, anyway.$_SERVER['DOCUMENT_ROOT'].'/error_log'错误日志中没有写入任何内容,无论如何,所有 PHP 错误都记录到该日志中。 In my home folder, there is a logs folder, but it remains empty.在我的主文件夹中,有一个logs文件夹,但它仍然是空的。 No logs in /etc/ or /etc/my_website_name.com either. /etc//etc/my_website_name.com也没有日志。

What could be causing this problem?什么可能导致这个问题? Is there something in the PHP.ini I could change?我可以更改 PHP.ini 中的某些内容吗? Could .htaccess affect this at all? .htaccess 会影响这个吗?

At the very least, how do I troubleshoot this problem?至少,我该如何解决这个问题?

Troubleshooting故障排除

  • I can submit an article which only contains - PHP Version 7.2.19-0ubuntu0.19.04.1 (from `phpinfo()`) in the body.我可以提交一篇正文中仅包含- PHP 版本 7.2.19-0ubuntu0.19.04.1(来自`phpinfo()`)的文章。
  • If I remove phpinfo() and add more content to the body of the post (more total data being submitted), it works如果我删除 phpinfo() 并向帖子正文添加更多内容(提交的总数据更多),它就可以工作
  • putting a space, like php info() makes it work, and is how the post currently exists.放置一个空格,如php info()使其工作,并且是当前帖子的存在方式。
  • I don't know what else to do我不知道还能做什么

I am using Simple MDE now, but it happened on multiple other occasions before I started using Simple MDE.我现在正在使用Simple MDE ,但在我开始使用 Simple MDE 之前,它发生在其他多个场合。 It has only been with relatively large posts that also contain code.只有相对较大的帖子也包含代码。

I am on Shared Hosting with HostGator, using HTTPS:// and PHP 7.2.19我与 HostGator 共享主机,使用 HTTPS:// 和 PHP 7.2.19

I contacted HostGator.我联系了HostGator。 They added something to a white list, but didn't give me intimate details.他们在白名单中添加了一些内容,但没有告诉我私密的细节。 It fixed the problem.它解决了这个问题。

First agent took awhile, failed to resolve the issue, and disconnected prematurely.第一个代理花了一段时间,未能解决问题,并提前断开连接。

The second agent was reasonably prompt & resolved the problem, saying I shouldn't have this issue with similar types of POST requests which contain code.第二个代理合理地提示并解决了问题,他说我不应该在包含代码的类似类型的 POST 请求中遇到这个问题。

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

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