摘要:通過類提供的方法分別獲取本類和父類中的屬性,然后進行對比剔除父類的屬性,保留本類的屬性,此方法返回的是一個類對象。
問題描述
上個星期碰到個客戶使用swoole compiler加密drupal導致drupal項目無法運行的問題,逐步排查后總結問題是drupal中有部分代碼直接通過file_get_contents獲取php源碼導致的,因為項目代碼是加密過后的,所以直接獲取php源碼解析是獲取不到想要的內容的。
加密框架drupalDrupal是使用PHP語言編寫的開源內容管理框架,下載完后需要進行相關的配置和安裝才能進行使用。
在加密后的影響drupal代碼運行的主要問題:代碼路徑:drupal/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionParser.php:126
protected function parse() { if ($this->parsed || !$fileName = $this->finder->findFile($this->className)) { return; } $this->parsed = true; $contents = file_get_contents($fileName); if ($this->classAnnotationOptimize) { if (preg_match("/A.*^s*((abstract|final)s+)?classs+{$this->shortClassName}s+/sm", $contents, $matches)) { $contents = $matches[0]; } } $tokenParser = new TokenParser($contents); ...... }
其中部分代碼如上,通過class名獲取文件路徑,然后通過file_get_contents()獲取php文件的內容,TokenParser類中構造函數如下
public function __construct($contents) { $this->tokens = token_get_all($contents); token_get_all("numTokens = count($this->tokens); }
傳入獲取到的源碼通過token_get_all()進行解析,然后后續分析代碼獲取php文件的類、屬性、方法的注釋 ,父類的命名空間 和class名 ,本類的use信息 等,因為文件已經加密,所以file_get_contents獲取到的內容是加密后的內容,token_get_all就解析不到正確的信息。
解決方案:
注:本次使用的2.1.1版本的加密器,通過swoole compiler加密器加密的代碼,在配置文件中save_doc配置選項一定要設置為1,如果設置為0則不會保存注釋,如果設置為0,在2.1.3版本swoole_loader.so擴展中新增加的函數naloinwenraswwww也無法獲取到類中use的相關信息,具體函數使用在后面會詳細說明。
$ref = new ReflectionClass($this->className); $parent_ref = $ref->getParentClass(); ...... if (is_file($fileName)) { $php_file_info = unserialize(naloinwenraswwww(realpath($fileName))); foreach ($php_file_info as $key => $info) { if ($key == "swoole_namespaces" || $key == "swoole_class_name") { continue; } $this->useStatements[$key] = $info; } } $this->parentClassName = $parent_ref->getName(); if (strpos($this->parentClassName, "")!==0) { $this->parentClassName = "".$this->parentClassName; } $static_properties = []; $properties = $ref->getProperties(); $parent_properties = $this->createNewArrKey($parent_ref->getProperties()); ...... $static_methods = []; $methods = $ref->getMethods(); ......
1.通過類名來獲取反射類ReflectionClass類的對象。
2.因為此反射類包含了所有父類中的屬性和方法,但源碼中只要獲取本類中的屬性和方法,所以還要獲取父類的反射類然后通過對比來剔除父類中的屬性和方法,可以使用ReflectionClass類提供的getParentClass()方法獲取父類的反射類,此方法返回父類的ReflectionClass對象。
3.通過ReflectionClass類提供的getProperties()方法分別獲取本類和父類中的屬性,然后進行對比剔除父類的屬性,保留本類的屬性,此方法返回的是一個ReflectionProperty類對象。
4.通過ReflectionProperty類提供的getDocComment()方法就可以拿到屬性的注釋。
5.同上通過ReflectionClass類提供的getMethods()方法可以拿到本類和父類中的方法,然后進行對比剔除父類的方法,保留本類的方法,此方法返回的是一個ReflectionMethod類對象。
6.通過ReflectionMethod對象提供的getDocComment()方法就可以拿到方法的注釋。
7.通過ReflectionClass提供的getName()方法可以拿到類名。
ps:因為反射無法獲取use類的信息,所以在2.1.3版本中的swoole_loader.so擴展中添加函數naloinwenraswwww(),此函數傳入一個php文件的絕對路徑,返回傳入文件的相關信息的序列化數組,反序列化后數組如下
[ "swoole_namespaces" => "DrupalCoreDatetimeElement", "swoole_class_name" => "DrupalCoreDatetimeElementDateElementBase", "nestedarray" => "DrupalComponentUtilityNestedArray", "drupaldatetime" => "DrupalCoreDatetimeDrupalDateTime", "formelement"=> "DrupalCoreRenderElementFormElement" ]
其中swoole_namespaces為文件的命名空間,swoole_class_name為文件的命名空間加類名,其他為use信息,鍵為use類的類名小寫字母,如存在別名則為別名的小寫字母,值為use類的命名空間加類名,通過該函數和反射函數可以兼容StaticReflectionParser中加密后出現的無法獲取正確信息的問題
在加密后的未影響drupal代碼運行的潛在問題:代碼路徑:drupal/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php:39
drupal中引入了Symfony框架,此框架中部分代碼也是通過file_get_contents和token_get_all來獲取php文件的類名,但目前未對druapl運行產生影響,可能并未用到其中方法
代碼路徑:drupal/vendor/symfony/class-loader/ClassMapGenerator.php:91
代碼路徑:drupal/vendor/symfony/routing/Loader/AnnotationFileLoader.php:90
解決方案:同StaticReflectionParser類的解決方案一樣通過2.1.3版本中的swoole_loader.so擴展中添加函數naloinwenraswwww()來獲取加密后文件的命名空間和類名
尚未有更好方案的問題:代碼路徑:drupal/core/includes/install.inc:220
function drupal_rewrite_settings($settings = [], $settings_file = NULL) { if (!isset($settings_file)) { $settings_file = Drupal::service("site.path") . "/settings.php"; } // Build list of setting names and insert the values into the global namespace. $variable_names = []; $settings_settings = []; foreach ($settings as $setting => $data) { if ($setting != "settings") { _drupal_rewrite_settings_global($GLOBALS[$setting], $data); } else { _drupal_rewrite_settings_global($settings_settings, $data); } $variable_names["$" . $setting] = $setting; } $contents = file_get_contents($settings_file); if ($contents !== FALSE) { // Initialize the contents for the settings.php file if it is empty. if (trim($contents) === "") { $contents = " $setting) { $buffer .= _drupal_rewrite_settings_dump($setting, "$" . $name); } // Write the new settings file. if (file_put_contents($settings_file, $buffer) === FALSE) { throw new Exception(t("Failed to modify %settings. Verify the file permissions.", ["%settings" => $settings_file])); } else { // In case any $settings variables were written, import them into the // Settings singleton. if (!empty($settings_settings)) { $old_settings = Settings::getAll(); new Settings($settings_settings + $old_settings); } // The existing settings.php file might have been included already. In // case an opcode cache is enabled, the rewritten contents of the file // will not be reflected in this process. Ensure to invalidate the file // in case an opcode cache is enabled. OpCodeCache::invalidate(DRUPAL_ROOT . "/" . $settings_file); } } else { throw new Exception(t("Failed to open %settings. Verify the file permissions.", ["%settings" => $settings_file])); } }
drupal安裝過程中有個配置文件default.setting.php,里面存放了默認配置數組,在安裝的過程中會讓用戶在安裝界面輸入一些配置比如mysql的信息,輸入過后此方法通過file_get_contents和token_get_all來獲取setting中的信息,然后合并用戶在頁面輸入的信息,重新存回文件,因為整個過程涉及到讀取文件,更改文件信息,在存入文件,所以swoole compiler在此處暫時沒有更好的解決方案,需要在加密的時候選擇不加密setting文件。
代碼路徑:drupal/vendor/symfony/class-loader/ClassCollectionLoader.php:126
此類中是symfony讀取php文件然后作相應處理后緩存到文件中,存在和上面代碼同樣的問題,暫未找到更好的解決方案
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31535.html
摘要:第行通過類提供的方法分別獲取本類和父類中的屬性,然后進行對比剔除父類的屬性,保留本類的屬性,此方法返回的是一個類對象。 前言 上個星期碰到個客戶使用Swoole Compiler加密Drupal導致Drupal項目無法運行的問題,逐步排查后總結問題是Drupal中有部分代碼直接通過file_get_contents獲取PHP源碼導致的,因為項目代碼是加密過后的,所以直接獲取PHP源碼解...
摘要:偏巧的是重定向的過程會給黑客提供中間人攻擊。在上例的情況下,從發送頭部到得到響應,有效性可保持年。它認為這個頭部可以預防偽造跨站請求。總結使用以上頭部可幫你快速容易地預防攻擊點擊挾持攻擊嗅探和中間人攻擊。請確保用戶的安全性。 它曾是世界性圖書館夢的開始,現在它是全球知識的聚集地,它是目前最流行的,人們將應用都部署之上的萬維網。 它是敏捷的代表,它不是單一的實體,它由客戶端和服務端組成...
摘要:問題首先你電腦上,系統是是安裝了很多版本的,其次,你的引用改了之后有多個引起多個版本擴展共存的問題即如在我本地為目錄下然后在目錄下會是這樣這種情況下使用進行安裝將會出現的情況,這樣你使用會一起報這個問題,如果不是這個問題就不用往下看了。 問題 首先,你電腦上,系統是Ubuntu是安裝了很多版本的PHP,其次,你的PHP引用改了之后有多個引起多個版本擴展共存的問題即如在我本地為/etc/...
閱讀 2312·2021-11-15 11:38
閱讀 2440·2021-11-15 11:37
閱讀 2543·2021-08-24 10:00
閱讀 2901·2019-08-30 15:56
閱讀 1260·2019-08-30 15:53
閱讀 3695·2019-08-29 18:43
閱讀 2930·2019-08-29 17:01
閱讀 3255·2019-08-29 16:25