通过 SSL 与 Laravel 的 MySQL 连接

Posted

技术标签:

【中文标题】通过 SSL 与 Laravel 的 MySQL 连接【英文标题】:MySQL connection over SSL with Laravel 【发布时间】:2019-04-03 07:27:16 【问题描述】:

我在 Laravel 应用程序中通过 ssl 连接到我的数据库时遇到问题。我的配置如下:

       'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
            'sslmode' => 'require',
            'options'   => array(
                PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
                PDO::MYSQL_ATTR_SSL_KEY => '/certs/client-key.pem',
                PDO::MYSQL_ATTR_SSL_CERT => '/certs/client-cert.pem',
                PDO::MYSQL_ATTR_SSL_CA => '/certs/ca.pem',
            ),
        ],

DB_CONNECTION=mysql
DB_HOST=xxx.xxx.xxx.xxx
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=db_user
DB_PASSWORD=xxxx

这些设置在 MySQL 服务器上给我以下错误。

2018-10-30T09:18:25.403712Z 71 [Note] Access denied for user 'user'@'xxx.xxx.xxx.xxx' (using password: YES)

通过 mysql-client 它可以在客户端服务器上完美运行。

mysql -u user -p -h xxx.xxx.xxx.xxx --ssl-ca=/certs/ca.pem --ssl-cert=/certs/client-cert.pem --ssl-key=/certs/client-key.pem

在与上述命令连接时在客户端执行的“\s”命令的输出。

mysql  Ver 15.1 Distrib 10.1.26-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

Connection id:      16
Current database:   database
Current user:       user@xxx.xxx.xxx.xxx
SSL:            Cipher in use is DHE-RSA-AES256-SHA
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server:         MySQL
Server version:     5.7.24-0ubuntu0.18.10.1 (Ubuntu)
Protocol version:   10
Connection:     167.99.215.179 via TCP/IP
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:       3306
Uptime:         23 min 29 sec

Threads: 2  Questions: 38  Slow queries: 0  Opens: 135  Flush tables: 1  Open tables: 128  Queries per second avg: 0.026
--------------

应用程序在基于 php:7.2.11-fpm 映像的 docker 容器中运行。并且配置了以下php扩展。

RUN docker-php-ext-install bcmath zip pdo_mysql json tokenizer

MySQL 版本:

Server version: 5.7.24-0ubuntu0.18.10.1 (Ubuntu)

PHP版本:

PHP 7.2.11 (cli) (built: Oct 16 2018 00:46:29) ( NTS )

PDO 版本:

PDO

PDO support => enabled
PDO drivers => sqlite, mysql

pdo_mysql

PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.12-dev - 20150407 - $Id: 38fea24f2847fa7519001be390c98ae0acafe387

OpenSSL 版本:

openssl

OpenSSL support => enabled
OpenSSL Library Version => OpenSSL 1.1.0f  25 May 2017
OpenSSL Header Version => OpenSSL 1.1.0f  25 May 2017
Openssl default config => /usr/lib/ssl/openssl.cnf

Directive => Local Value => Master Value
openssl.cafile => no value => no value
openssl.capath => no value => no value

对此有什么想法吗?这让我忙了好几个小时......

【问题讨论】:

您是否尝试将PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT 设置为true @Egretos 这给出了以下错误。 3 [Note] Bad handshake 证书是自签名的。 您的 PHP 版本、openSSL 版本和 PDO 和 PDO MySQL 版本是什么?您可以在phpinfo(); 中查看每个。还有什么是 MySQL 服务器的版本。请不要评论和更新问题。您的 MySQL 服务器是否配置为处理 SSL 连接?还要记住,使用 SSL 连接到 localhost 是没有意义的。 @emix 我已经更新了这个问题。 MySQL 如果配置为 SSL,我还添加了在连接 mysql-client 时在客户端服务器上执行的\s 的输出。 【参考方案1】:

我终于解决了这个问题。上面的配置实际上很好。我直接在 docker 容器中工作。由于某种原因,配置保存在缓存中。

以下命令未清除配置缓存:

php artisan config:clear
php artisan config:cache
php artisan cache:clear

当我创建一个新用户来连接数据库以测试某些东西时,我注意到了这一点。我使用新配置重建容器,现在一切正常。

【讨论】:

有类似的问题。只想问路径 certs/client-key.pem 是客户端服务器上的路径吗?我如何找出配置的内容?【参考方案2】:

    请检查您的 .env 文件。此文件将位于网站根文件夹中。

    DB_CONNECTION=mysql
    DB_HOST=hostip
    DB_PORT=3306
    DB_DATABASE=database_name
    DB_USERNAME=database_user_name
    DB_PASSWORD=database_password
    

2.也更新配置-> database.php 文件为:

    'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'sslmode' => env('DB_SSLMODE', 'prefer'),
        'options'   => array(
            PDO::MYSQL_ATTR_SSL_CA      => '/home/.../ca-cert.pem',
            PDO::MYSQL_ATTR_SSL_CERT    => '/home/.../cert.pem',
            PDO::MYSQL_ATTR_SSL_KEY     => '/home/.../key.pem'
        ),
        'strict' => true,
        'engine' => null,
    ],

【讨论】:

感谢您的回答。我弄清楚出了什么问题,您可以在我的答案中阅读。基本上,cache:clear `config:cache',... 没有清除我的环境缓存。重建和部署一个新容器就可以了。

以上是关于通过 SSL 与 Laravel 的 MySQL 连接的主要内容,如果未能解决你的问题,请参考以下文章

通过 SSL 的 Spring Boot 远程 Mysql 连接

Cakephp 3 - 通过SSL连接MySQL

Laravel 基础 url 显示非 SSL url()

laravel 队列守护进程邮件因 SSL 错误而停止运行

为啥mysql客户端不使用--ssl-ca操作可以通过私有IP连接到启用SSL的mysql5.6,但不能通过公共IP?

配置spring通过ssl连接mysql