我已经阅读了很多这方面的帖子,似乎没有任何共识。我正在为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
}
?>
答案 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
}