簡體   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