PhpMyadmin 令牌认证系统
PhpMyadmin Token Authentification system
我最近有了一个想法,即使用存储在数据库中的登录凭据创建的令牌创建 PhpMyAdmin 的登录系统。
url 看起来像这样:
pma.example.com/index.php?token=WCxuFWj1QtGGapZhfSPS9Eo1Q9q666sR
令牌包含 32 个随机生成的字母数字字符。
所以我有一个 API 在 Python 中用 Flask 制作,它在本地与 PhpMyadmin 和不同的应用程序进行通信,它有两条路线:
127.0.0.1:4040/api/v1/create_token
[POST] 此请求具有作为 JSON 参数 database_host_id
的 MySQL 主机 ID 以连接定义在 PhpMyAdmin 配置文件中,database_username
这是写入数据库用户连接,最后 database_host
这是数据库密码。响应有一个 token
参数供客户端接收新生成的令牌。
发送和接收的 JSON 应该是这样的:
JSON received by the API :
{
"database_host_id": 1,
"database_username": "pma",
"database_password: "4wAyS8",
}
JSON sent to the client:
{
"token": "WCxuFWj1QtGGapZhfSPS9Eo1Q9q666sR"
}
127.0.0.1:4040/api/v1/get_database
[POST] 此请求有一个 JSON 参数 token
以了解从哪个令牌检索连接信息。因此响应将包含所有这些信息以及 database_host_id
、database_username
和 database_password
。发送和接收的 JSON 应该是这样的:
JSON received by the API :
{
"token": "WCxuFWj1QtGGapZhfSPS9Eo1Q9q666sR"
}
JSON sent to the client :
{
"database_host_id": 1,
"database_username": "pma",
"database_password: "4wAyS8",
}
有一个API很好,但是如果你不使用它,它就没用了,所以我在 PhpMyAdmin 的源代码中搜索了身份验证系统是如何工作的。
我能理解:
/libraries/common.inc.php
该脚本将在运行时使用所谓的 AuthPlugin
和这段代码,然后被各种 classes 用作登录界面:
$auth_plugin = Plugins::getAuthPlugin();
$auth_plugin->authenticate();
- 我通过查看与此 class 关联的不同功能来了解
AuthPlugin
是什么。我推断 libraries/classes/Plugins/Auth
中的所有文件都是连接插件,并允许为我们在 PhpMyAdmin 配置文件中使用 $cfg['Servers'][$i]['auth_type']
定义的 MySQL 主机定义不同的连接方法。知道默认的认证类型是Cookie,就去查看文件内容librairies/classes/Plugins/Auth/AuthenticationCookie.php
.
所以现在我不得不修改 AuthenticationCookie.php
脚本,以便当 token
包含在 URL 中时,它可以从 API 中检索信息,然后使用它连接到与该令牌关联的数据库。
这就是我陷入困境的地方,因为尽管我有 PHP 基础知识,但我无法将我正在做的事情付诸实践。尽管我尝试过,但我注意到当我从 URL 检索令牌时,它根本不是定义的内容,就好像它是加密的。
所以这是我的问题:
- 即使 API 仅在本地通信,我是否应该加密密码?
- 我的 MySQL 主机不应该只使用 SignOn 连接方法吗?
- 做我想做的事情安全吗?
信息:
- PhpMyAdmin 版本:5.1.3
我将不胜感激任何帮助我推理或回答我的问题
我最终制作了一个与我的服务器关联的 SignOn 脚本,该脚本从 URL 获取令牌,向 API 询问令牌信息,然后与其连接。它完美运行。
<?php
/**
* Single signon for phpMyAdmin
*
* This is just example how to use session based single signon with
* phpMyAdmin, it is not intended to be perfect code and look, only
* shows how you can integrate this functionality in your application.
*/
declare(strict_types=1);
/* Use cookies for session */
ini_set('session.use_cookies', 'true');
/* Change this to true if using phpMyAdmin over https */
$secure_cookie = false;
/* Need to have cookie visible from parent directory */
session_set_cookie_params(0, '/', '', $secure_cookie, true);
/* Create signon session */
$session_name = 'SignonSession';
session_name($session_name);
// Uncomment and change the following line to match your $cfg['SessionSavePath']
//session_save_path('/foobar');
@session_start();
/* Was data posted? */
if (isset($_REQUEST['token'])) {
$data = array(
'token'=> $_REQUEST['token']
);
$payload = json_encode($data);
$curl = curl_init('http://127.0.0.1:4040/api/v1/get_database');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$response = json_decode($response, true);
/* Store there credentials */
$_SESSION['PMA_single_signon_user'] = $response->database_username;
$_SESSION['PMA_single_signon_password'] = $response->database_password;
$_SESSION['PMA_single_signon_host'] = $_POST['host'];
$_SESSION['PMA_single_signon_port'] = $_POST['port'];
/* Update another field of server configuration */
$_SESSION['PMA_single_signon_cfgupdate'] = ['verbose' => 'Signon test'];
$_SESSION['PMA_single_signon_HMAC_secret'] = hash('sha1', uniqid(strval(rand()), true));
$id = session_id();
/* Close that session */
@session_write_close();
/* Redirect to phpMyAdmin (should use absolute URL here!) */
header('Location: ../index.php');
} else {
/* Show simple form */
header('Content-Type: text/html; charset=utf-8');
echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
echo '<!DOCTYPE HTML>
<html lang="en" dir="ltr">
<head>
<link rel="icon" href="../favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
<meta charset="utf-8">
<title>Loading...</title>
</head>
<body>';
if (isset($_SESSION['PMA_single_signon_error_message'])) {
echo '<p class="error">';
echo $_SESSION['PMA_single_signon_error_message'];
echo '</p>';
}
echo '
<h1>Loading...</h1>
</body>
</html>';
}
我知道它还没有完成,但我打算改进它。所以这就是我找到的解决方案。
我最近有了一个想法,即使用存储在数据库中的登录凭据创建的令牌创建 PhpMyAdmin 的登录系统。 url 看起来像这样:
pma.example.com/index.php?token=WCxuFWj1QtGGapZhfSPS9Eo1Q9q666sR
令牌包含 32 个随机生成的字母数字字符。
所以我有一个 API 在 Python 中用 Flask 制作,它在本地与 PhpMyadmin 和不同的应用程序进行通信,它有两条路线:
127.0.0.1:4040/api/v1/create_token
[POST] 此请求具有作为 JSON 参数database_host_id
的 MySQL 主机 ID 以连接定义在 PhpMyAdmin 配置文件中,database_username
这是写入数据库用户连接,最后database_host
这是数据库密码。响应有一个token
参数供客户端接收新生成的令牌。 发送和接收的 JSON 应该是这样的:
JSON received by the API :
{
"database_host_id": 1,
"database_username": "pma",
"database_password: "4wAyS8",
}
JSON sent to the client:
{
"token": "WCxuFWj1QtGGapZhfSPS9Eo1Q9q666sR"
}
127.0.0.1:4040/api/v1/get_database
[POST] 此请求有一个 JSON 参数token
以了解从哪个令牌检索连接信息。因此响应将包含所有这些信息以及database_host_id
、database_username
和database_password
。发送和接收的 JSON 应该是这样的:
JSON received by the API :
{
"token": "WCxuFWj1QtGGapZhfSPS9Eo1Q9q666sR"
}
JSON sent to the client :
{
"database_host_id": 1,
"database_username": "pma",
"database_password: "4wAyS8",
}
有一个API很好,但是如果你不使用它,它就没用了,所以我在 PhpMyAdmin 的源代码中搜索了身份验证系统是如何工作的。
我能理解:
/libraries/common.inc.php
该脚本将在运行时使用所谓的AuthPlugin
和这段代码,然后被各种 classes 用作登录界面:
$auth_plugin = Plugins::getAuthPlugin();
$auth_plugin->authenticate();
- 我通过查看与此 class 关联的不同功能来了解
AuthPlugin
是什么。我推断libraries/classes/Plugins/Auth
中的所有文件都是连接插件,并允许为我们在 PhpMyAdmin 配置文件中使用$cfg['Servers'][$i]['auth_type']
定义的 MySQL 主机定义不同的连接方法。知道默认的认证类型是Cookie,就去查看文件内容librairies/classes/Plugins/Auth/AuthenticationCookie.php
.
所以现在我不得不修改 AuthenticationCookie.php
脚本,以便当 token
包含在 URL 中时,它可以从 API 中检索信息,然后使用它连接到与该令牌关联的数据库。
这就是我陷入困境的地方,因为尽管我有 PHP 基础知识,但我无法将我正在做的事情付诸实践。尽管我尝试过,但我注意到当我从 URL 检索令牌时,它根本不是定义的内容,就好像它是加密的。
所以这是我的问题:
- 即使 API 仅在本地通信,我是否应该加密密码?
- 我的 MySQL 主机不应该只使用 SignOn 连接方法吗?
- 做我想做的事情安全吗?
信息:
- PhpMyAdmin 版本:5.1.3
我将不胜感激任何帮助我推理或回答我的问题
我最终制作了一个与我的服务器关联的 SignOn 脚本,该脚本从 URL 获取令牌,向 API 询问令牌信息,然后与其连接。它完美运行。
<?php
/**
* Single signon for phpMyAdmin
*
* This is just example how to use session based single signon with
* phpMyAdmin, it is not intended to be perfect code and look, only
* shows how you can integrate this functionality in your application.
*/
declare(strict_types=1);
/* Use cookies for session */
ini_set('session.use_cookies', 'true');
/* Change this to true if using phpMyAdmin over https */
$secure_cookie = false;
/* Need to have cookie visible from parent directory */
session_set_cookie_params(0, '/', '', $secure_cookie, true);
/* Create signon session */
$session_name = 'SignonSession';
session_name($session_name);
// Uncomment and change the following line to match your $cfg['SessionSavePath']
//session_save_path('/foobar');
@session_start();
/* Was data posted? */
if (isset($_REQUEST['token'])) {
$data = array(
'token'=> $_REQUEST['token']
);
$payload = json_encode($data);
$curl = curl_init('http://127.0.0.1:4040/api/v1/get_database');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$response = json_decode($response, true);
/* Store there credentials */
$_SESSION['PMA_single_signon_user'] = $response->database_username;
$_SESSION['PMA_single_signon_password'] = $response->database_password;
$_SESSION['PMA_single_signon_host'] = $_POST['host'];
$_SESSION['PMA_single_signon_port'] = $_POST['port'];
/* Update another field of server configuration */
$_SESSION['PMA_single_signon_cfgupdate'] = ['verbose' => 'Signon test'];
$_SESSION['PMA_single_signon_HMAC_secret'] = hash('sha1', uniqid(strval(rand()), true));
$id = session_id();
/* Close that session */
@session_write_close();
/* Redirect to phpMyAdmin (should use absolute URL here!) */
header('Location: ../index.php');
} else {
/* Show simple form */
header('Content-Type: text/html; charset=utf-8');
echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
echo '<!DOCTYPE HTML>
<html lang="en" dir="ltr">
<head>
<link rel="icon" href="../favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
<meta charset="utf-8">
<title>Loading...</title>
</head>
<body>';
if (isset($_SESSION['PMA_single_signon_error_message'])) {
echo '<p class="error">';
echo $_SESSION['PMA_single_signon_error_message'];
echo '</p>';
}
echo '
<h1>Loading...</h1>
</body>
</html>';
}
我知道它还没有完成,但我打算改进它。所以这就是我找到的解决方案。