我需要确认成功的PDO连接

时间:2016-01-22 22:42:04

标签: php mysql pdo

我已经阅读了很多这方面的帖子,似乎没有任何共识。我正在为Web应用程序编写一个开源通用安装程序,我需要确认一个成功的PDO连接。它需要测试PDO连接,然后它将编写实际的config / init文件。文件编写部分工作正常,但我似乎无法得到PDO真正连接的具体验证。如果表单为空,它表示已连接,如果表单中的某些信息正确,则表示已连接。如何清楚地表明pdo凭据是否正确?我会给你一个(精简版)我正在做的事情。

表格:

<H2>Please fill in your database credentials</H2>
<form class="form" action="" method="post">
  <label for="dbh">Database Host
  <input class="form-control" type="text" name="dbh"  value="<?php if (!empty($_POST['dbh'])){ print $_POST['dbh']; } ?>"></label><br><br>

  <label for="dbu">Database User
  <input class="form-control" type="text" name="dbu"  value="<?php if (!empty($_POST['dbu'])){ print $_POST['dbu']; } ?>"></label><br><br>

  <label for="dbp">Database Password
  <input class="form-control" type="text" name="dbp"  value="<?php if (!empty($_POST['dbp'])){ print $_POST['dbp']; } ?>"></label><br><br>

  <label for="dbn">Database Name
<input class="form-control" type="text" name="dbn"  value="<?php if (!empty($_POST['dbn'])){ print $_POST['dbn']; } ?>"></label><br><br>

PHP

<?php
if (!empty($_POST)) {
    $dbh=$_POST['dbh']; //db host
    $dbu=$_POST['dbu']; //db username
    $dbp=$_POST['dbp']; //db password
    $dbn=$_POST['dbn']; //database name

    //If Testing
    if (!empty($_POST['test'])) {
        $dsn = "mysql:host=$dbh;dbname=$dbn;charset=utf8";
        $opt = array(
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
            );
        $pdo = new PDO($dsn, $dbu, $dbp, $opt);
     }

    //todo:  If Submitted, a bunch more logic here
}
?>

1 个答案:

答案 0 :(得分:5)

如果存在任何连接错误,将抛出PDOException对象。

try {
    $pdo = new PDO($dsn, $dbu, $dbp, $opt);
} catch (PDOException $e) {
    // bad connection
}

要验证主机名,数据库名和登录凭据等数据是否正确,您必须强制用户不要将这些数据留空。实际上,完全可以与主机建立连接,这是因为mysql允许创建具有与任何用户名匹配的空白用户名(空字符串)的帐户。

另外,为了避免dsn字符串中的参数注入(例如,名为foo;port=123的数据库名称),您至少应检查连接中是否存在分号或NULL字节选项(作为主机e数据库名称)。

实施例

/**
 * Return a PDO object if the connection options are correct, and if the connection is established. False otherwhise.
 */
function test_mysql_connection($host, $dbname, $username, $password = null) {
    if (empty($host) || empty($dbname) || empty($username)) {
        // those parameters MUST NOT be empty
        throw new InvalidArgumentException('Host, database name and username are required.')
    }

    try {
        $pdo = new PDO(build_mysql_dsn_safely($host, $dbname), $username, $password);
        return $pdo;
    } catch (PDOException $e) {
        // bad connection
        return false;
    }
}

/**
 * See how is it parsed here: https://github.com/php/php-src/blob/71c19800258ee3a9548af9a5e64ab0a62d1b1d8e/ext/pdo/pdo.c#L207
 */
function build_mysql_dsn_safely($host, $dbname = null, $charset = null, $port = null)
{
    static $bad_chars = array(';', '=', "\0");

    $vars = array_filter(array(
        'host' => $host,
        'dbname' => $dbname,
        'charset' => $charset,
        'port' => $port,
    ));

    foreach($vars as $param => $data) {
        foreach ($bad_chars as $bad_char) {
            if (strpos($data, $bad_char) !== false) {
                throw new InvalidArgumentException(sprintf(
                    'Connection options "%s" contains an invalid value.', $param
                ));
            }
        }
    }

    return 'mysql:'.implode(';', array_map(function($optkey, $optval) {
        return $optkey.'='.$optval;
    }, array_keys($vars), $vars));
}

if($pdo = test_mysql_connection($_POST['dbh'], $_POST['dbu'], $_POST['dbn'], $_POST['dbp'])) {
    // connection established
}