【问题标题】:Admin username/password isn't working for PHP管理员用户名/密码不适用于 PHP
【发布时间】:2013-12-10 20:09:19
【问题描述】:

所以我目前正在学习 PHP 编程课程,我终于进入了身份验证和授权的艺术。

因此,在本书中,我们首先限制了授予所有帐户访问权限的页面,您可以在其中更新和删除所有帐户。我们从定义常量开始:

define('VALID_USERNAME', '');
define('VALID_PASSWORD', '');

为了方便我自己,我只是把它们作为空字符串。

一切顺利,弹出询问用户名和密码的对话框。 但是,当我输入空字符串时,对话框不断弹出,好像密码错误,或者根本没有输入密码。即使我用真实字符串定义用户名和密码,也会发生这种情况。

这是我的那部分代码:

if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
    header('http/1.1 401 Unauthorized');
    header('WWW-Authenticate: Basic realm="Wonder Penguin"');
} else {
    if (($_SERVER['PHP_AUTH_USER'] != VALID_USERNAME) ||
        ($_SERVER['PHP_AUTH_PW'] != VALID_PASSWORD)) {
        header('http/1.1 401 Unauthorized');
        header('WWW-Authenticate: Basic realm="Wonder Penguin"');
    }
}

如果您想知道为什么我没有使用 exit() 函数来防止人们点击取消以绕过身份验证并进入更新页面。我这样做是为了让我的老师可以对我创建的最后一个作业的这个页面进行评分。

我已经厌倦了排错:

我使用 echo 函数测试了我是否正确定义了有效的用户名和密码。

echo VALID_USERNAME;
echo VALID_PASSWORD;

它会弹出我定义的内容。所以理论上,我认为我的定义是正确的。

我尝试用单引号、双引号和不带引号编写define 函数。 这本书要我写这样的函数:

define(VALID_USERNAME, "admin");
define(VALID_PASSWORD, "password");

但是,当我试图在那里定义它们时,这会带来一个错误,即我使用了一个未定义的常量。

var_dump($_SERVER); 结果:

array(37) {

["REDIRECT_HANDLER"]=> string(23) "application/x-httpd-php"
["REDIRECT_STATUS"]=> string(3) "200"
["HTTP_HOST"]=> string(20) "patti-bee2.dcccd.edu"
["HTTP_CONNECTION"]=> string(10) "keep-alive"
["HTTP_ACCEPT"]=> string(74) "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
["HTTP_USER_AGENT"]=> string(108) "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"
["HTTP_ACCEPT_ENCODING"]=> string(17) "gzip,deflate,sdch"
["HTTP_ACCEPT_LANGUAGE"]=> string(14) "en-US,en;q=0.8"
["HTTP_COOKIE"]=> string(217) "__qca=P0-630369357-1378011844686; __utma=198331962.264424896.1377179965.1382812794.1384740700.12; __utmc=198331962; __utmz=198331962.1381981575.8.4.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)"
["PATH"]=> string(135) "C:\Program Files (x86)\PHP\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;c:\php;"
["SystemRoot"]=> string(10) "C:\Windows"
["COMSPEC"]=> string(27) "C:\Windows\system32\cmd.exe"
["PATHEXT"]=> string(53) ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC"
["WINDIR"]=> string(10) "C:\Windows"
["SERVER_SIGNATURE"]=> string(0) ""
["SERVER_SOFTWARE"]=> string(21) "Apache/2.2.22 (Win32)"
["SERVER_NAME"]=> string(20) "patti-bee2.dcccd.edu"
["SERVER_ADDR"]=> string(14) "144.162.99.193"
["SERVER_PORT"]=> string(2) "80"
["REMOTE_ADDR"]=> string(11) "99.7.247.36"
["DOCUMENT_ROOT"]=> string(66) "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs"
["SERVER_ADMIN"]=> string(16) "pburks@dcccd.edu"
["SCRIPT_FILENAME"]=> string(106) "C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs\Coleman\Wonder Penguin\PHP\show_all.php"
["REMOTE_PORT"]=> string(5) "54619"
["REDIRECT_URL"]=> string(40) "/coleman/wonder penguin/php/show_all.php"
["GATEWAY_INTERFACE"]=> string(7) "CGI/1.1"
["SERVER_PROTOCOL"]=> string(8) "HTTP/1.1"
["REQUEST_METHOD"]=> string(3) "GET"
["QUERY_STRING"]=> string(0) ""
["REQUEST_URI"]=> string(42) "/coleman/wonder%20penguin/php/show_all.php"
["SCRIPT_NAME"]=> string(40) "/coleman/wonder penguin/php/show_all.php"
["ORIG_SCRIPT_FILENAME"]=> string(18) "C:/PHP/php-cgi.exe"
["ORIG_PATH_INFO"]=> string(40) "/coleman/wonder penguin/php/show_all.php"
["ORIG_PATH_TRANSLATED"]=> string(106) "C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs\Coleman\Wonder Penguin\PHP\show_all.php"
["ORIG_SCRIPT_NAME"]=> string(16) "/php/php-cgi.exe"
["PHP_SELF"]=> string(40) "/coleman/wonder penguin/php/show_all.php"
["REQUEST_TIME"]=> int(1385432192)
}

在这一点上,我几乎直接从书中复制了它。 我做错了什么?

如果你想自己尝试一下,这里是link to my site

【问题讨论】:

  • 我对您正在使用的这本书持怀疑态度。正如您所发现的,您绝对应该使用它们的名称作为字符串define('VALID_USERNAME', 'admin') 来定义常量。另外作为代码风格说明,考虑使用' 表示字符串文字而不是",这样你就不会对变量或转义字符感到惊讶`. ('` 在理论上更快。)无论如何,我我想知道var_dump($_SERVER) 的输出是什么。那应该可以帮助您调试它。我怀疑如果用户名/密码为空,这些变量根本不会出现。
  • @Brad,我刚试了一下,遇到了一大堆错误。
  • 没有错,就是你需要的调试输出!它基本上是$_SERVER 超全局关联数组中的每个变量。一些服务器使用除PHP_AUTH_USERPHP_AUTH_PW 之外的其他名称。我想看看那个输出是什么。您可以将其粘贴到您的问题中吗?
  • @Brad,你去吧,先生。
  • $_SERVER 中没有任何授权。当你做调试输出时,你是先登录的吗?如果是这样,Apache 的 CGI 参数很可能以某种方式配置不正确。不过,再次尝试使用用户名/密码的某些内容(不仅仅是空字符串)登录。

标签: php authentication admin


【解决方案1】:

使用以下代码以获得最佳效果,例如

定义(VALID_USERNAME,“管理员”); 定义(VALID_PASSWORD,“密码”);

如果 (($_SERVER['PHP_AUTH_USER'] != VALID_USERNAME) || ($_SERVER['PHP_AUTH_PW'] != VALID_PASSWORD)) {

header('WWW-Authenticate: Basic realm="Wonder Penguin"');
header('HTTP/1.0 401 Unauthorized');

退出; }

【讨论】:

    【解决方案2】:

    试试这个

    define('VALID_USERNAME', '');
    define('VALID_PASSWORD', '');
    
    if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']))
    {
        header('http/1.1 401 Unauthorized');
        header('WWW-Authenticate: Basic realm="Wonder Penguin"');
        echo "Fail";
    }
    else
    {
        if (($_SERVER['PHP_AUTH_USER'] != VALID_USERNAME) ||
            ($_SERVER['PHP_AUTH_PW'] != VALID_PASSWORD))
        {
            header('http/1.1 401 Unauthorized');
            header('WWW-Authenticate: Basic realm="Wonder Penguin"');
            echo "Fail";
        }
        else
        {
            echo "SUccess";
        }
    }
    

    【讨论】:

      【解决方案3】:

      这种全局变量用户名和登录状态存储在会话中,因此我们可以全局存储,我更喜欢存储在会话中而不是将其定义为常量

      【讨论】:

        【解决方案4】:

        我知道我不是专家或擅长清楚地解释事情,但据我所知,问题在于如何使用基本身份验证以及将基本身份验证的标头放在哪里(对我来说只是不要放冗余。):

        这里有一段代码可以帮助您使用基本身份验证:

        包含用户名和密码等凭据。出于安全目的,我不建议使用 define()。

        if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']))
        {
           $valid_user = 'admin';
           $valid_password = 'password';
           if($_SERVER['PHP_AUTH_USER'] == $valid_user && $_SERVER['PHP_AUTH_PW'] == $valid_password)
           {
              $response = array('Response'  => true,
                                'Message'   => 'Welcome! ' . $valid_user);
        
              $result = json_encode($response);
              echo $result;
           }
           else
           {
              $response = array('Response'  => false,
                                'Message'   => 'User and Password does not match!');
        
              $result = json_encode($response);
              echo $result;
              exit();
           }
        }
        else
        {
           header('WWW-Authenticate: Basic realm="Wonder Penguin"');
           header('HTTP/1.0 401 Unauthorized');
        
           $response = array('Response' => false,
                             'Message'  => '401 Unauthorized!');
        
           $result = json_encode($response);
           echo $result;
           exit();
        }
        

        就是这样,尽情学习吧!

        【讨论】:

          【解决方案5】:

          从 php5.6 开始,您可以在编译时使用 const。这意味着您不能像 define 那样在运行时将它们分配在条件内部。

          const VALID_USERNAME = "admin";      // global
          const VALID_PASSWORD = "password";   // global
          
          class CREDENTIALS {
              const VALID_USERNAME = "admin";     // not global
              const VALID_PASSWORD = "password";  // not global
          }
          
          
          echo CREDENTIALS::VALID_USERNAME;  // "admin"
          echo CREDENTIALS::VALID_PASSWORD;  // "password"
          
          if(!defined("VALID_USERNAME")){
              echo "the constant VALID_USERNAME is not defined";
          }
          
          
          if(isset($_SERVER['SOMETHING'])){
             const VALID_USERNAME = "admin";     // won't work
             const VALID_PASSWORD = "password";  // won't work
          }
          
          if(isset($_SERVER['SOMETHING'])){
             define("VALID_USERNAME","admin");     //  works
             define("VALID_PASSWORD","password");  // works
          }
          
          
          1. 常量必须在创建时赋值。
          2. 常量只能用常量值初始化,不能用表达式初始化。
          3. const 可用于创建全局常量。这样的常量是在全局范围内定义的,可以在脚本的任何地方访问
          4. const 可以在类或接口内使用来定义类常量或接口常量。
          5. 类常量的引用方式与静态属性相同
          6. define 不能用于此目的。

          或者如果你想创建一个数组

          class CREDENTIALS {
              const ARR = [
                  VALID_USERNAME => "admin",
                  VALID_PASSWORD => "password"
              ]
          }
          
          echo CREDENTIALS::ARR['VALID_USERNAME']; // "admin",
          echo CREDENTIALS::ARR['VALID_PASSWORD']; // "password"
          
          

          从 php7 开始,您现在还可以常量定义为数组

          define(ARR, [
           "VALID_USERNAME" => "admin",
           "VALID_PASSWORD" => "password"
          ]);
          
          echo ARR["VALID_USERNAME"]; // "admin"
          echo ARR["VALID_PASSWORD"]; // "password"
          

          如果您使用命名空间,const 始终在当前命名空间中定义常量,而使用 define 您必须始终使用完整的命名空间名称

          namespace SOME\NAME\SPACE;
          
              const VALID_USERNAME = "admin";
              const VALID_PASSWORD = "password";
          
              define("SOME\NAME\SPACE\VALID_USERNAME", "admin");
              define("SOME\NAME\SPACE\VALID_PASSWORD", "password");
          

          【讨论】:

            【解决方案6】:

            也许是因为您正在使用 OR。您是说如果用户名无效或密码无效则显示 401。尝试将其设为 && 吗?这样他们就必须拥有准确的用户名和密码。

            if (($_SERVER['PHP_AUTH_USER'] != VALID_USERNAME) ||
                ($_SERVER['PHP_AUTH_PW'] != VALID_PASSWORD)) {
            header('http/1.1 401 Unauthorized');
            header('WWW-Authenticate: Basic realm="Wonder Penguin"');
                }
            

            【讨论】:

            • "试着把它改成 &&?这样他们必须有准确的用户名和密码。" --- 恰恰相反。 || 在那里正确使用。
            【解决方案7】:

            这很简单: 如果您以编程方式设置用户名和密码,请尝试此操作(如果使用登录页面!)

            <?php
            $username = $_POST['username'];
            $password = $_POST['password'];
            $cu = "admin";
            $cpw = "password";
            if($username = $cu && $password = $cpw){
            //Code to be executed
            }else{
            if condition is false
            }
            ?>
            

            【讨论】:

            • 没有登录页面...使用基本身份验证。
            • 此外,如果您想评估它们是相同的,而不是简单地将 $username 更改为'管理员'
            猜你喜欢
            • 2020-06-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-01-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多