CakePHP com conexão segura ao MySQL
No projeto de um de nossos clientes, surgiu a necessidade de configurar uma conexão segura a um servidor MySQL para garantir a segurança dos dados, pois a conexão seria através da internet.
Consideramos algumas opções, entre elas:
- Túnel SSH
- VPN
- Criptografia nativa do MySQL via SSL
Após alguns testes, concluímos que a criptografia nativa do MySQL via SSL é simples de ser configurada e garante a segurança dos dados, além de não precisar de um utilitário externo (SSH, OpenVPN, etc).
No PHP, os dois drivers nativos para MySQL – mysql e mysqli – suportam a conexão criptografada. Basta usar o método Mysqli::ssl_set:
1 | $connection->ssl_set($key,$cert,$ca,$capath,$cipher); |
Porém, descobrimos que os conectores para MySQL do CakePHP (1.2, 1.3 e 2.0) não tem essa funcionalidade. Decidimos então implementar um novo conector baseado no original.
Adaptando o conector MySQL do CakePHP
Criamos o conector DboMysqliSsl, que extende DboMysqli, em cake/libs/model/datasources/dbo/dbo_mysqli_ssl.php e sobrescrevemos o método connect, responsável por estabelecer a conexão. O trecho destacado é a parte que difere da superclasse:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <?php App::import('Core', 'DboMysqli'); class DboMysqliSsl extends DboMysqli { function connect() { $config = $this->config; $this->connected = false; if (is_numeric($config['port'])) { $config['socket'] = null; } else { $config['socket'] = $config['port']; $config['port'] = null; } $this->connection = new mysqli(); $this->connection->init(); if (isset($config['ssl'])) { @$key = $config['ssl']['key']; @$cert = $config['ssl']['cert']; @$ca = $config['ssl']['ca']; @$capath = $config['ssl']['capath']; @$cipher = $config['ssl']['cipher']; $this->connection->ssl_set($key,$cert,$ca,$capath,$cipher); } @$flags = $config['flags']; $this->connected = $this->connection->real_connect($config['host'], $config['login'],$config['password'], $config['database'], $config['port'], $config['socket'], $flags); $this->_useAlias = (bool)version_compare(mysqli_get_server_info($this->connection), "4.1", ">="); if (!empty($config['encoding'])) { $this->setEncoding($config['encoding']); } return $this->connected; } } ?> |
Configurando sua conexão (database.php)
Agora, para que sua aplicação CakePHP consiga se conectar a um servidor MySQL com SSL, basta adicionar as seguintes configurações na sua conexão:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | array( 'driver' => 'mysqli_ssl', 'persistent' => false, 'host' => '127.0.0.1', 'login' => 'userssl', 'password' => 'password', 'database' => 'meu_sistema', 'prefix' => '', 'encoding'=>'utf8', 'flags' => MYSQL_CLIENT_SSL, 'ssl' => array( 'key' => '/path/to/meu_sistema/app/config/mysql_ssl/server-key.pem', 'cert' => '/path/to/meu_sistema/app/config/mysql_ssl/server-cert.pem', 'ca' => '/path/to/meu_sistema/app/config/mysql_ssl/ca-cert.pem', 'capath' => null, 'cipher' => null ) ) |
Como a configuração sugere, salve os arquivos indicados em um lugar acessível pela sua aplicação – no exemplo usamos /path/to/meu_sistema/app/config/mysql_ssl.
Configurando o MySQL para aceitar (ou exigir) conexões criptografadas
Para seu MySQL aceitar conexões criptografadas você terá que, primeiro, gerar os certificados conforme o tópico “Example 1: Creating SSL files from the command line on Unix” desta página do manual do MySQL.
Em seguida, você deve indicar esses certificados no arquivo de configuração do mysql (/etc/mysql/my.cnf no Debian e Ubuntu). Essa configuração já existe por volta da linha 118. Descomente essas linhas e indique o caminho dos seus certificados:
1 2 3 | ssl-ca=/etc/mysql/cacert.pem ssl-cert=/etc/mysql/server-cert.pem ssl-key=/etc/mysql/server-key.pem |
Reinicie seu MySQL:
1 | sudo /etc/init.d/mysql restart |
Agora, se você executar a seguinte query no MySQL:
1 | mysql> SHOW VARIABLES LIKE '%ssl%'; |
Você verá que o SSL está ativado.
Se você quiser exigir o uso do certificado para que um usuários consiga se conectar no seu servidor MySQL, você deve alterar a permissão do usuário, adicionando a opção REQUIRE SSL, conforme o exemplo:
1 | GRANT ALL PRIVILEGES ON *.* TO 'userssl'@'%' IDENTIFIED BY 'password' REQUIRE SSL; |
Pronto, agora você tem uma conexão segura entre sua aplicação CakePHP e seu banco de dados MySQL.
Para acessar seu MySQL com SSL via linha de comando, use os seguintes parâmetros:
1 | mysql -h127.0.0.1 -uuserssl -p --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem |
Open Source
Essa modificação foi sugerida para ser incorporada ao framework no Lighthouse do CakePHP.

Muito legal o post de vocês. Também achei legal a iniciativa de extender o framework para atender a necessidade do cliente. Isso demonstra que não vale a pena ficar parado diante de um problema, mas sim deve-se atacá-lo com o conhecimento necessário.
Parabéns
[...] This post was mentioned on Twitter by Jonas Alves and Flavio Logullo, webgoal. webgoal said: Novo Post no Blog da WebGoal – CakePHP com conexão segura ao MySQL por Jonas Alves e Herbertt Bamonde. http://bit.ly/bj3OsN [...]