作者:沈婧颖_491 | 来源:互联网 | 2023-09-13 11:42
我已经阅读了很多这方面的帖子,似乎没有任何共识.我正在为Web应用程序编写一个开源通用安装程序,我需要确认一个成功的PDO连接.它需要测试PDO连接,然后它将编写实际的config/init
我已经阅读了很多这方面的帖子,似乎没有任何共识.我正在为Web应用程序编写一个开源通用安装程序,我需要确认一个成功的PDO连接.它需要测试PDO连接,然后它将编写实际的config / init文件.文件编写部分工作正常,但我似乎无法得到PDO真正连接的具体验证.如果表单为空,它表示已连接,如果表单中的某些信息正确,则表示已连接.如何清楚地表明pdo凭据是否正确?我会给你一个(精简版)我正在做的事情.
表格:
Please fill in your database credentials
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
}
?>
解决方法:
如果存在任何连接错误,将抛出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
}