使用正则表达式验证类/方法名称

Validate class/method names with regex

提问人:RobertPitt 提问时间:7/7/2010 最后编辑:Dennis WilliamsonRobertPitt 更新时间:11/29/2021 访问量:7466

问:

我目前正在为一家公司开发 MVC 样式框架,出于安全原因,我需要确保通过查询字符串传递的控制器/方法是 RFC 的有效字符(我找不到)。

我需要能够根据 PHP 解释器允许的内容验证/清理类名

例如:

class SomEFunk__YClAssName extends Controller
{

}

我需要某种正则表达式来验证和清理它,如果需要的话!这也与方法的原理相同。SomEFunk__YClAssName

有几件事需要考虑,例如

  • 开头的数字
  • 只允许下划线
  • 允许某些 PHP 特殊字符。

有关此或可能的表达式的任何信息都将非常有帮助。

以下是我的一些路由器代码,因此您可以看到我需要在哪里实现它:

private function prepareQueryString()
    {
        if(strlen($this->query_string) == 0)
        {
            return;
        }
        //Remove [ending|starting|multiple] slashes
        $this->query_string = preg_replace('/^\/+|\/+$|\/(?=\/)/', '', $this->query_string);
        foreach(explode('/',$this->query_string) as $Key => $Value)
        {
            if($Key == 0)
            {
                $Controller = $this->AssignController($Value);
            }
            if($Key == 1)
            {
                $this->AssignMethod($Value);
            }else
            {
                $this->AssignParam($Value);
            }
        }

        //Build RouterVar stdClass
    }

    public function AssignController(String $Controller)
    {
        if(!empty($Controller))
        {
            //Sanitize
        }
    }

    public function AssignMethod(String $Method)
    {
        if(!empty($Method))
        {
            //Sanitize
        }
    }

    public function AssignParam(String $Param)
    {
        $this->params[] = $Param;
    }

您将在需要检查的地方看到注释“Sanitize”。

PHP 正则表达 式对象 方法

评论


答:

6赞 user229044 7/7/2010 #1

你最好使用一个非常通用的正则表达式,然后通过对 的简单调用来测试该类是否存在。class_exists()

这将匹配任何有效的 PHP 类名,包括非常奇怪的类名,例如 或 ,这两个类名都是有效的类名:____3

/^[a-z_]\w+$/i

我个人比PHP的类命名约定更严格。我要求我的控制器大写,并用后缀,这样奇怪的非控制器类就不会通过奇怪的 URL 调用。我会使用这样的东西:_controller

class Products_controller extends Controller { }

// elsewhere, after parsing the controller name from the URI:

if (preg_match('/^[A-Z]\w+_controller$/', $controller_name)
&&  class_exists($controller_name)) {
  $controller = new $controller_name();
}

顺便说一句,通过查询字符串传递控制器名称会产生非常丑陋且对搜索引擎不友好的 URL。请考虑将控制器名称和方法构建到 URL 中:

/products/index # controller=products, action=index
/users/show/3   # controller=users, action=show, user id=3

评论

0赞 RobertPitt 7/7/2010
我想出这样做,但仍然应该允许使用字符,例如和^(?=_*[A-z]+)[A-z0-9_]+$class €1{}class €€_{}
0赞 user229044 7/7/2010
如果你真的想调用任何任意命名的类,那么你所关心的只是类是否存在。完全跳过正则表达式,它没有添加任何安全方面的内容,只需检查 .class_exists()
0赞 Brad Kent 4/1/2020
调用将调用 Autoloader..并加载匹配的文件...这可能会导致副作用。在一个框架中(我不会命名),如果我这样做.php它的自动加载器将加载索引'class_exists('index')。这将尝试重新启动应用程序和致命错误class_exists
20赞 pinate 8/18/2012 #2

我相信您正在寻找的正则表达式短类名,例如 是:SomeClass

<?php

preg_match(
    '/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', 
    $input
);

根据:http://php.net/manual/en/language.oop5.basic.php


对于命名空间类,例如 是的:App\SomeClass

<?php

preg_match(
    '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*$/', 
    $input
);

评论

0赞 Xunnamius 6/16/2013
感谢您提供代码示例和文档链接。我会把这个标记为答案。
4赞 Michael Osl 9/14/2013
注意:我认为您的 存在缺陷,因为没有给出开始/结束分隔符。您的代码将返回 1。如果将其更改为,则返回 0。preg_match$input="Definitely Not A Valid Classname!"preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $input);
1赞 pinate 9/14/2013
对开始/结束分隔符的良好调用。
4赞 Josef Kufner 7/29/2016
如果要使用命名空间验证类名,请使用以下命令: --- 区别仅在于使用反斜杠分隔符重复模式。/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*$/
3赞 vee 12/3/2019
PHP 网站已更新为 . 对于@JosefKufner答案,反斜杠应该是 4。例:\x80\x7f^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*(\\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$