Symfony、Swoft 等框架的路由方式如果通过注释的方式是无法正确解析的,框架通过分析源码获得文件的命名空间,类名等信息,这些信息加密后都无法获得,验证方式:搜索框架源代码是否调用了 get_file_contents()、token_get_all() 等方法来解析 PHP源代码文件。
解决方案,参考 Drupal 加密
- 模板 view 文件如果有模板引擎的特殊标签也无法支持,因为模板引擎需要分析 view 的内容来解析替换,如果加密了就无法分析了,只能通过黑名单的方式排除 不要加密 view
Doctrine 注解
Symfony ORM 框架 Doctrine 中存在file_get_contents()读取PHP源代码解析use语法的逻辑。使用Doctrine的项目加密后无法正确读取。例如easyswoole框架使用了Doctrine,在代码中使用注解时出现问题。
项目代码
namespace App\HttpController\Test;
use App\Annotation\Test\CheckAuth;
class Test extends Base
{
/**
* @CheckAuth(only_login = true)
*/
function info() {
return $this->success('请求成功');
}
}
错误信息
[Semantical Error] The annotation "@CheckAuth" in method App\HttpController\Test\Auth::info() was never imported. Did you maybe forget to add a "use" statement for this annotation?
#0 /app/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(812): Doctrine\Common\Annotations\AnnotationException::semanticalError('The annotation ...')
#1 /app/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(726): Doctrine\Common\Annotations\DocParser->Annotation()
#2 /app/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(379): Doctrine\Common\Annotations\DocParser->Annotations()
#3 /app/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php(217): Doctrine\Common\Annotations\DocParser->parse('/**\r\n * @Ch...', 'method App\\Http...')
#4 /app/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php(225): Doctrine\Common\Annotations\AnnotationReader->getMethodAnnotations(Object(ReflectionMethod))
#5 /app/App/HttpController/Test/Base.php(51): Doctrine\Common\Annotations\AnnotationReader->getMethodAnnotation(Object(ReflectionMethod), 'App\\Annotation\\...')
#6 /app/vendor/easyswoole/http/src/AbstractInterface/Controller.php(161): App\HttpController\Test\Base->onRequest('info')
#7 /app/vendor/easyswoole/http/src/AbstractInterface/Controller.php(153): EasySwoole\Http\AbstractInterface\Controller->__exec()
#8 /app/vendor/easyswoole/http/src/Dispatcher.php(229): EasySwoole\Http\AbstractInterface\Controller->__hook('info', Object(EasySwoole\Http\Request), Object(EasySwoole\Http\Response))
#9 /app/vendor/easyswoole/http/src/Dispatcher.php(183): EasySwoole\Http\Dispatcher->controllerExecutor(Object(EasySwoole\Http\Request), Object(EasySwoole\Http\Response), '/Test/auth/info')
#10 /app/vendor/easyswoole/easyswoole/src/Core.php(264): EasySwoole\Http\Dispatcher->dispatch(Object(EasySwoole\Http\Request), Object(EasySwoole\Http\Response))
AnnotationReader.php
class AnnotationReader implements Reader
{
// ...
private function collectParsingMetadata($reflection): void
{
$type = $reflection instanceof ReflectionClass ? 'class' : 'function';
$name = $reflection->getName();
$ignoredAnnotationNames = self::$globalIgnoredNames;
$annotations = $this->preParser->parse($reflection->getDocComment(), $type . ' ' . $name);
foreach ($annotations as $annotation) {
if (! ($annotation instanceof IgnoreAnnotation)) {
continue;
}
foreach ($annotation->names as $annot) {
$ignoredAnnotationNames[$annot] = true;
}
}
$this->imports[$type][$name] = array_merge(
self::$globalImports,
$this->phpParser->parseUseStatements($reflection),
[
'__NAMESPACE__' => $reflection->getNamespaceName(),
'self' => $name,
]
);
$this->ignoredAnnotationNames[$type][$name] = $ignoredAnnotationNames;
}
// ...
}
PhpParser.php
class PhpParser {
// ...
public function parseUseStatements($reflection): array
{
if (method_exists($reflection, 'getUseStatements')) {
return $reflection->getUseStatements();
}
$filename = $reflection->getFileName();
if ($filename === false) {
return [];
}
$content = $this->getFileContent($filename, $reflection->getStartLine());
if ($content === null) {
return [];
}
$namespace = preg_quote($reflection->getNamespaceName());
$content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
$tokenizer = new TokenParser('<?php ' . $content);
return $tokenizer->parseUseStatements($reflection->getNamespaceName());
}
// ...
}
解决方案
修改vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php,在$globalImports数组中手动添加所有需要use引入的类。
class AnnotationReader implements Reader
{
private static $globalImports = [
'ignoreannotation' => Annotation\IgnoreAnnotation::class,
'checkauth' => \App\Annotation\Test\CheckAuth::class,
];