【问题标题】:Validate class/method names with regex使用正则表达式验证类/方法名称
【发布时间】:2011-03-12 20:33:59
【问题描述】:

我目前正在为一家公司开发 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;
    }

您会在需要检查的地方看到注释“消毒”。

【问题讨论】:

    标签: php regex object methods


    【解决方案1】:

    我相信您正在寻找短类名称的正则表达式,例如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
    );
    

    【讨论】:

    • 感谢您提供代码示例和文档链接。我会将此标记为答案。
    • 注意:我认为您的preg_match 存在缺陷,因为没有给出开始/结束分隔符。 $input="Definitely Not A Valid Classname!" 的代码将返回 1。如果将其更改为 preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $input);,它将返回 0。
    • 对开始/结束分隔符的良好调用。
    • 如果您想使用命名空间验证类名,请使用:/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*$/ --- 不同之处仅在于使用反斜杠分隔符重复该模式。
    • PHP 网站已更新为 \x80 而不是 \x7f^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$ 和 @JosefKufner 的答案,反斜杠应该是 4。例如:^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*(\\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$
    【解决方案2】:

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

    这将匹配任何有效的 PHP 类名,包括像 ____3 这样非常奇怪的类名,它们都是有效的类名:

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

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

    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
    

    【讨论】:

    • 我想这样做^(?=_*[A-z]+)[A-z0-9_]+$,但仍然应该允许使用字符,例如class €1{}class €€_{}
    • 如果你真的想调用任意命名的类,那么你真正关心的只是类的存在。完全跳过正则表达式,它不会增加任何安全性,只需检查class_exists()
    • 调用class_exists 将调用自动加载器......并加载匹配的文件......这可能会导致副作用......在框架中(我不会命名),它的自动加载器将加载索引。 php 如果我执行 `class_exists('index').. 这将尝试重新引导应用程序和致命错误
    猜你喜欢
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    相关资源
    最近更新 更多