Aula 19: Usuários e permissões — GRANT, REVOKE e segurança

Aula 19: Usuários e permissões — GRANT, REVOKE e segurança

Nesta aula vamos mergulhar em um dos pilares mais críticos da administração de bancos de dados MySQL: o gerenciamento de usuários e permissões. Diferentemente de muitos sistemas que tratam autenticação e autorização de forma simplificada, o MySQL possui um modelo extremamente granular — ele permite controlar exatamente o que cada conta pode ou não pode fazer, em quais objetos (global, banco, tabela ou até coluna) e a partir de quais hosts. Compreender esse modelo é obrigatório para qualquer profissional de TI que deseja proteger dados, evitar acessos indevidos e manter a integridade de ambientes produtivos. Ao longo desta aula, você aprenderá a criar usuários, conceder privilégios com GRANT, revogá-los com REVOKE, verificar as permissões atribuídas e resolver os erros mais comuns relacionados ao controle de acesso.

O domínio de usuários e permissões no MySQL não é apenas uma habilidade técnica — é uma necessidade de segurança da informação. Uma configuração inadequada pode abrir brechas para ataques, vazamento de dados e comprometimento de servidores inteiros. Em nossa experiência na JRT Technology Solutions, já identificamos inúmeros ambientes onde contas com privilégios excessivos ou senhas fracas se tornaram a porta de entrada para incidentes. Por isso, esta lição adota uma abordagem prática e segura, alinhada ao princípio do menor privilégio: cada usuário deve ter exatamente as permissões necessárias para executar suas tarefas — nada mais, nada menos.

Antes de prosseguir, é importante que você já tenha concluído as aulas anteriores do curso, onde instalamos e configuramos o MySQL Server, aprendemos os comandos básicos do mysql client e exploramos a criação de bancos de dados e tabelas. Você precisará de acesso a um servidor MySQL em funcionamento, preferencialmente com privilégios de root ou de um usuário com a permissão CREATE USER e GRANT OPTION. Vamos trabalhar com comandos executados no terminal (linha de comando) do sistema operacional, mas os conceitos se aplicam a qualquer ferramenta de gerenciamento MySQL, como MySQL Workbench, phpMyAdmin ou DBeaver.

Ao final desta aula, você será capaz de criar contas de usuário seguras, definir políticas de acesso por host, conceder e revogar privilégios em diferentes escopos, visualizar as permissões concedidas, alterar métodos de autenticação, bloquear contas e solucionar erros de acesso. Também discutiremos boas práticas adotadas diariamente por nossos especialistas na JRT Technology Solutions e configuraremos um ambiente de teste real para verificação de cada comando.

O que você vai aprender nesta aula

  • Compreender o modelo de autenticação e autorização do MySQL, incluindo os níveis de privilégios.
  • Criar e gerenciar contas de usuário com CREATE USER, ALTER USER, DROP USER e RENAME USER.
  • Conceder privilégios com GRANT em escopos global, de banco, tabela, coluna e rotina.
  • Revogar privilégios com REVOKE e entender as implicações de cada operação.
  • Visualizar permissões efetivas com SHOW GRANTS e consultas às tabelas do sistema.
  • Gerenciar plugins de autenticação, incluindo mysql_native_password, caching_sha2_password e auth_socket.
  • Testar acessos, identificar e corrigir erros comuns como ERROR 1045, ERROR 1130 e ERROR 1142.
  • Aplicar boas práticas de segurança para usuários e permissões em produção.

Pré-requisitos e Ambiente

Para acompanhar esta aula de forma prática, você precisará de um servidor MySQL instalado e em execução. As aulas anteriores deste curso cobriram a instalação em sistemas Ubuntu/Debian e CentOS/RHEL/Rocky Linux, portanto você já deve ter o ambiente pronto. Verifique se o serviço está ativo com os seguintes comandos, conforme o seu sistema operacional:

# Para Ubuntu/Debian (systemd)
sudo systemctl status mysql

# Para CentOS/RHEL/Rocky Linux (systemd)
sudo systemctl status mysqld

Além disso, você deve ter acesso ao cliente mysql e a uma conta com privilégios administrativos. No Ubuntu/Debian, a instalação padrão cria um usuário root que se autentica via auth_socket — isso significa que o acesso administrativo é feito com sudo mysql sem senha. Já no CentOS/RHEL/Rocky, a instalação gera uma senha temporária para o root e exige que você a altere no primeiro acesso. Em ambos os casos, tenha em mãos as credenciais adequadas.

Se estiver utilizando um ambiente de produção, recomendamos fortemente que você execute os comandos desta aula primeiro em um servidor de testes. Em nossos projetos na JRT Technology Solutions, sempre validamos mudanças de permissões em ambientes de homologação antes de aplicá-las em produção, para evitar impactos indesejados.

Fundamentos de Usuários e permissões no MySQL

O MySQL adota um modelo de controle de acesso baseado em contas compostas por duas partes: o nome de usuário e o host de origem. Por exemplo, ‘ana’@’localhost’ e ‘ana’@’192.168.1.50’ são consideradas contas completamente distintas, mesmo compartilhando o mesmo nome. Essa distinção é essencial porque permite definir regras diferentes dependendo de onde a conexão se origina. Um usuário ‘root’@’localhost’ pode ter acesso total, enquanto ‘root’@’%’ (qualquer host) pode ser totalmente negado ou limitado.

As informações sobre usuários e permissões são armazenadas em tabelas do banco de dados mysql, que é o dicionário de dados do próprio servidor. As principais tabelas são: mysql.user (contas e privilégios globais), mysql.db (privilégios em nível de banco), mysql.tables_priv (privilégios em tabelas), mysql.columns_priv (privilégios em colunas) e mysql.procs_priv (privilégios em stored procedures e funções). Quando você executa um comando GRANT, o servidor atualiza essas tabelas automaticamente e, em versões recentes, também recarrega os dados em memória — não sendo necessário executar FLUSH PRIVILEGES na maioria dos casos.

Os privilégios no MySQL são organizados em diferentes níveis hierárquicos. O nível global se aplica a todos os bancos de dados do servidor; o nível de banco de dados se restringe a um schema específico; o nível de tabela limita a uma tabela; o nível de coluna permite conceder acesso apenas a determinadas colunas de uma tabela; e o nível de rotina se aplica a procedures e funções. Essa granularidade é um dos pontos fortes do MySQL, pois possibilita criar políticas de acesso extremamente precisas.

A tabela a seguir resume os principais níveis de privilégio, os objetos aos quais se aplicam e onde são armazenados:

Nível de Privilégio Objeto Alvo Tabela de Armazenamento Exemplo de Concessão
Global Todos os bancos e tabelas do servidor mysql.user GRANT SELECT ON *.* TO ‘user’@’host’;
Banco de dados Todas as tabelas de um banco específico mysql.db GRANT SELECT ON db1.* TO ‘user’@’host’;
Tabela Todas as colunas de uma tabela específica mysql.tables_priv GRANT SELECT ON db1.tab TO ‘user’@’host’;
Coluna Apenas colunas específicas de uma tabela mysql.columns_priv GRANT SELECT (col1, col2) ON db1.tab TO ‘user’@’host’;
Rotina Procedures e funções armazenadas mysql.procs_priv GRANT EXECUTE ON PROCEDURE db1.proc TO ‘user’@’host’;

Além dos níveis, os privilégios individuais definem as operações permitidas. Os mais comuns incluem SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX, GRANT OPTION (permissão para conceder privilégios a outros) e ALL PRIVILEGES (todos os privilégios, exceto GRANT OPTION). Existem também privilégios administrativos globais como RELOAD, SHUTDOWN, PROCESS e FILE, que devem ser concedidos com extrema cautela.

Criando Usuários e permissões com CREATE USER

Para criar uma nova conta de usuário no MySQL, utilizamos o comando CREATE USER. Esse comando define o nome da conta, o host de origem e a senha inicial. A sintaxe básica é a seguinte:

CREATE USER 'nome_usuario'@'host' IDENTIFIED BY 'senha_segura';

Vamos iniciar um procedimento prático completo. Primeiro, conecte-se ao servidor MySQL como usuário administrativo. No Ubuntu/Debian, o padrão é usar autenticação via socket, então o comando será:

# Conectar como root via socket (Ubuntu/Debian)
sudo mysql

Já no CentOS/RHEL/Rocky Linux, a autenticação root é por senha, então utilize:

# Conectar como root via senha (CentOS/RHEL/Rocky)
mysql -u root -p

Após entrar no prompt do MySQL (indicado por mysql>), execute o comando CREATE USER para criar uma conta de teste. Observe que usaremos o host localhost para restringir o acesso apenas à máquina local. A senha escolhida deve seguir boas práticas: mínimo de 12 caracteres, combinação de letras maiúsculas, minúsculas, números e símbolos.

-- Criar um usuário local chamado 'app_user' com senha forte
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'Senha@Forte#2026';

-- Criar um usuário que pode se conectar de qualquer host (cuidado!)
CREATE USER 'app_remote'@'%' IDENTIFIED BY 'Outra@Senha#2026';

-- Criar um usuário restrito a um IP específico
CREATE USER 'app_lan'@'192.168.1.100' IDENTIFIED BY 'Senha@Lan#2026';

O primeiro comando cria a conta app_user que só pode autenticar a partir do próprio servidor (localhost). O segundo cria app_remote que pode se conectar de qualquer host — essa prática deve ser evitada em produção a menos que haja uma necessidade real. O terceiro cria app_lan restrito a um IP específico da rede local. A saída esperada para cada comando bem-sucedido é:

Query OK, 0 rows affected (0.01 sec)

É importante destacar que o CREATE USER apenas cria a conta, não concede nenhum privilégio. O usuário recém-criado poderá conectar-se ao servidor, mas não terá permissão nem mesmo para visualizar bancos de dados. Para conceder acesso, precisamos do comando GRANT, que será detalhado na próxima seção.

Vamos verificar se as contas foram criadas corretamente consultando a tabela mysql.user. Execute o comando abaixo:

-- Consultar usuários criados
SELECT User, Host, plugin FROM mysql.user WHERE User IN ('app_user', 'app_remote', 'app_lan');

A saída esperada mostrará as três contas com seus respectivos hosts e o plugin de autenticação padrão. Em servidores MySQL 8.0 ou superior, o plugin padrão é caching_sha2_password, enquanto versões antigas usam mysql_native_password.

+-------------+----------------+-----------------------+
| User        | Host           | plugin                |
+-------------+----------------+-----------------------+
| app_user    | localhost      | caching_sha2_password |
| app_remote  | %              | caching_sha2_password |
| app_lan     | 192.168.1.100  | caching_sha2_password |
+-------------+----------------+-----------------------+
3 rows in set (0.00 sec)

Agora que as contas existem, precisamos conceder permissões. Mas antes, entenda: em versões recentes do MySQL, o comando GRANT não cria mais usuários automaticamente (a menos que você utilize uma sintaxe específica e o servidor esteja configurado para isso). Por isso, a ordem correta é sempre CREATE USER primeiro e GRANT depois.

Concedendo Usuários e permissões com GRANT

O comando GRANT é a principal ferramenta para atribuir privilégios a contas de usuário. Sua sintaxe geral é:

GRANT  ON  TO 'usuário'@'host' [WITH GRANT OPTION];

Os privilégios podem ser listados separados por vírgula, e o objeto define o escopo. Para conceder privilégios globais, usamos *.*; para um banco específico, nome_banco.*; para uma tabela, nome_banco.nome_tabela; e para colunas específicas, colocamos a lista entre parênteses antes do ON. Vamos aos exemplos práticos.

Suponha que o usuário app_user precise de acesso de leitura e escrita a um banco de dados chamado vendas. Execute o comando abaixo:

-- Conceder SELECT, INSERT, UPDATE e DELETE no banco vendas
GRANT SELECT, INSERT, UPDATE, DELETE ON vendas.* TO 'app_user'@'localhost';

A saída esperada é:

Query OK, 0 rows affected (0.01 sec)

Agora, o usuário app_user pode executar operações de leitura e modificação em todas as tabelas do banco vendas, mas não pode criar, alterar ou excluir tabelas, nem acessar outros bancos. Esse é um exemplo típico de permissão de aplicação web: a aplicação só precisa ler e gravar dados, não administrar a estrutura do banco.

Para conceder privilégios administrativos globais, como CREATE, DROP, ALTER e INDEX, use o escopo *.*. No exemplo a seguir, criamos um usuário com poderes de administração de banco de dados, mas sem o perigo do GRANT OPTION:

-- Conceder privilégios globais de administração de banco de dados
GRANT CREATE, DROP, ALTER, INDEX, SELECT, INSERT, UPDATE, DELETE ON *.* TO 'db_admin'@'localhost';

Se você deseja que esse usuário também possa criar outros usuários e gerenciar permissões, é necessário adicionar CREATE USER e GRANT OPTION. Contudo, essa combinação é extremamente poderosa e deve ser reservada para administradores de confiança. Em nossos projetos na JRT Technology Solutions, raramente concedemos GRANT OPTION a contas de aplicação, justamente para evitar que um eventual comprometimento da aplicação permita a escalação de privilégios.

-- Conceder todos os privilégios com capacidade de repassar permissões
GRANT ALL PRIVILEGES ON *.* TO 'super_admin'@'localhost' WITH GRANT OPTION;

Também é possível conceder permissões em nível de coluna. Imagine que o usuário relatorio_user precise apenas ler as colunas nome e email da tabela clientes no banco vendas. O comando seria:

-- Conceder SELECT apenas nas colunas nome e email da tabela clientes
GRANT SELECT (nome, email) ON vendas.clientes TO 'relatorio_user'@'localhost';

Essa granularidade é útil em cenários de compliance, como LGPD, onde o acesso a dados pessoais deve ser minimizado. No entanto, privilégios em coluna são armazenados em tabelas separadas e podem exigir verificações adicionais de performance em consultas complexas.

A tabela a seguir resume os privilégios mais comuns e o que cada um permite, para servir de referência rápida:

Privilégio Descrição Escopo Típico
ALL PRIVILEGES Todos os privilégios disponíveis, exceto GRANT OPTION Qualquer
SELECT Permite ler dados (SELECT) Global, banco, tabela, coluna
INSERT Permite inserir linhas Global, banco, tabela, coluna
UPDATE Permite modificar linhas existentes Global, banco, tabela, coluna
DELETE Permite excluir linhas Global, banco, tabela
CREATE Permite criar bancos de dados ou tabelas Global, banco
DROP Permite excluir bancos de dados, tabelas ou views Global, banco
ALTER Permite alterar a estrutura de tabelas (ALTER TABLE) Global, banco, tabela
INDEX Permite criar ou remover índices Global, banco, tabela
EXECUTE Permite executar stored procedures e funções Global, banco, rotina
GRANT OPTION Permite conceder privilégios a outros usuários Qualquer
CREATE USER Permite criar, alterar e remover contas de usuário Global

Após conceder permissões, é essencial verificar se elas foram aplicadas corretamente. O comando SHOW GRANTS FOR ‘usuário’@’host’ exibe as permissões efetivas. Vamos verificar o usuário app_user:

-- Verificar permissões do app_user
SHOW GRANTS FOR 'app_user'@'localhost';

A saída esperada mostrará as permissões concedidas, incluindo a linha que o MySQL gera automaticamente para permitir a conexão:

+---------------------------------------------------------------------------------------------+
| Grants for app_user@localhost                                                               |
+---------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `app_user`@`localhost`                                                |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `vendas`.* TO `app_user`@`localhost`                |
+---------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Note que a linha GRANT USAGE ON *.* indica apenas que a conta existe e pode conectar, mas não concede nenhum privilégio real. Essa linha aparece sempre que uma conta é criada, mesmo sem permissões adicionais.

Revogando Usuários e permissões com REVOKE

Assim como o GRANT concede privilégios, o comando REVOKE os remove. A sintaxe é semelhante, mas troca TO por FROM:

REVOKE  ON  FROM 'usuário'@'host';

Vamos supor que, por uma mudança de requisitos, o usuário app_user não deva mais poder excluir registros no banco vendas. Para revogar apenas o privilégio DELETE, execute:

-- Revogar DELETE do app_user no banco vendas
REVOKE DELETE ON vendas.* FROM 'app_user'@'localhost';

A saída esperada:

Query OK, 0 rows affected (0.01 sec)

Após a revogação, o usuário ainda poderá fazer SELECT, INSERT e UPDATE, mas qualquer tentativa de DELETE resultará em erro de permissão. Essa granularidade é extremamente útil em ambientes dinâmicos, onde as necessidades de acesso mudam com frequência.

Para revogar todos os privilégios de uma conta de uma só vez, utilize a sintaxe REVOKE ALL PRIVILEGES, GRANT OPTION FROM …. Isso remove tanto os privilégios quanto a capacidade de repassá-los. Veja o exemplo:

-- Revogar todos os privilégios e GRANT OPTION do super_admin
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'super_admin'@'localhost';

É importante entender que REVOKE ALL PRIVILEGES não exclui a conta — apenas remove todas as permissões concedidas. A conta continua existindo e pode se autenticar, mas não conseguirá executar nenhuma operação além de conectar. Para remover completamente a conta, use DROP USER, que veremos mais adiante.

Outro ponto crítico: se um usuário possui permissões em múltiplos níveis (por exemplo, global e em um banco específico), revogar em um nível não afeta o outro. Por exemplo, se ana tem SELECT global e DELETE no banco vendas, revogar DELETE em *.* não removerá o DELETE de vendas.*. Você precisa revogar cada concessão separadamente no escopo correto.

Visualizando Usuários e permissões com SHOW GRANTS

O comando SHOW GRANTS é a forma mais direta de verificar as permissões de um usuário. Ele pode ser executado para o usuário atualmente conectado (sem a cláusula FOR) ou para uma conta específica:

-- Ver permissões do usuário atual
SHOW GRANTS;

-- Ver permissões de um usuário específico
SHOW GRANTS FOR 'app_user'@'localhost';

Além do SHOW GRANTS, é possível consultar diretamente as tabelas de privilégios no banco mysql. Por exemplo, para listar todas as contas e seus privilégios globais, execute:

-- Consultar tabela mysql.user para ver contas e privilégios globais
SELECT User, Host, Select_priv, Insert_priv, Update_priv, Delete_priv, Grant_priv
FROM mysql.user
WHERE User NOT IN ('mysql.sys', 'mysql.session', 'mysql.infoschema');

A saída será uma tabela com uma linha para cada conta, exibindo Y (sim) ou N (não) para cada privilégio global. Essa abordagem é útil para auditorias em lote, pois permite exportar os dados para ferramentas de análise. Em nossos projetos na JRT Technology Solutions, frequentemente automatizamos consultas como essa para gerar relatórios mensais de conformidade de acesso.

Para verificar permissões em nível de banco, consulte mysql.db; para tabelas, mysql.tables_priv; e para colunas, mysql.columns_priv. Cada tabela tem uma estrutura ligeiramente diferente, mas todas compartilham as colunas User e Host para identificar a conta.

-- Consultar permissões em nível de banco de dados
SELECT User, Host, Db, Select_priv, Insert_priv, Update_priv, Delete_priv
FROM mysql.db
WHERE User = 'app_user';

Essa consulta retornará uma linha para o banco vendas, mostrando os privilégios que foram concedidos no escopo do banco. É uma ótima maneira de auditar o que cada aplicação pode fazer em cada schema.

Alterando e Gerenciando Usuários e permissões (ALTER USER, DROP USER, RENAME USER)

O gerenciamento de usuários e permissões não se limita a criar e conceder. Muitas vezes precisamos alterar senhas, bloquear contas, renomeá-las ou removê-las completamente. O comando ALTER USER é a ferramenta para essas tarefas. Vejamos os casos mais comuns.

Para alterar a senha de um usuário existente, execute:

-- Alterar a senha do app_user
ALTER USER 'app_user'@'localhost' IDENTIFIED BY 'Nova@Senha#2026';

Se o usuário esquecer a senha e precisar redefini-la, um administrador com privilégio CREATE USER pode executar o mesmo comando. A saída esperada é Query OK, 0 rows affected. Após a alteração, a senha antiga deixa de funcionar imediatamente.

Para bloquear uma conta temporariamente, sem removê-la, use a cláusula ACCOUNT LOCK. Isso impede que o usuário se autentique, mas mantém todos os privilégios intactos para quando for desbloqueado:

-- Bloquear a conta app_remote
ALTER USER 'app_remote'@'%' ACCOUNT LOCK;

-- Desbloquear a conta app_remote
ALTER USER 'app_remote'@'%' ACCOUNT UNLOCK;

O bloqueio de contas é uma prática recomendada para funcionários em férias, contas de serviço em manutenção ou suspeitas de comprometimento. É reversível e não afeta os privilégios concedidos.

Para renomear uma conta, use RENAME USER. Isso é útil quando um usuário muda de função ou quando queremos padronizar nomes:

-- Renomear app_user para web_app_user
RENAME USER 'app_user'@'localhost' TO 'web_app_user'@'localhost';

A saída:

Query OK, 0 rows affected (0.01 sec)

Finalmente, para remover completamente uma conta e todos os seus privilégios, use DROP USER:

-- Remover a conta app_lan
DROP USER 'app_lan'@'192.168.1.100';

Após a execução, a conta não poderá mais se conectar. Se houver outros usuários que foram criados por essa conta com GRANT OPTION, eles não serão afetados diretamente, mas a remoção de um administrador pode ter implicações em auditorias. Recomendamos sempre revisar o SHOW GRANTS antes de executar DROP USER.

Configuração de Autenticação e Plugins em Usuários e permissões

O MySQL suporta diferentes plugins de autenticação que determinam como as credenciais são verificadas. Os mais comuns são:

Plugin Descrição Uso Típico
caching_sha2_password Padrão no MySQL 8.0+. Usa SHA-256 com cache e pode exigir conexão segura (TLS) para troca de senha. Novas instalações MySQL 8.0+
mysql_native_password Método tradicional baseado em SHA-1. Compatível com clientes antigos. Legado ou compatibilidade
sha256_password Autenticação SHA-256 sem cache. Requer TLS ou par de chaves RSA. Ambientes com alta segurança
auth_socket Usa o usuário do sistema operacional para autenticar via socket Unix. Não usa senha. Root local no Ubuntu/Debian

No Ubuntu/Debian, a instalação padrão do MySQL configura o usuário root para usar auth_socket. Isso significa que, ao executar sudo mysql, o servidor verifica o usuário do sistema operacional (root) e permite a conexão sem pedir senha. Essa abordagem é segura porque apenas o root do sistema pode acessar o MySQL como root, mas pode surpreender administradores acostumados com o CentOS/RHEL, onde o root usa senha e o plugin é caching_sha2_password (ou mysql_native_password em versões antigas).

Para alterar o plugin de autenticação de um usuário, utilize ALTER USER … IDENTIFIED WITH. Por exemplo, se você precisa que um usuário criado com caching_sha2_password funcione com um cliente antigo que só suporta mysql_native_password, execute:

-- Alterar plugin de autenticação para mysql_native_password
ALTER USER 'web_app_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Senha@Compart#2026';

Também é possível verificar o plugin atual de cada conta com a consulta:

-- Ver plugin de autenticação dos usuários
SELECT User, Host, plugin FROM mysql.user;

Em nossos projetos na JRT Technology Solutions, recomendamos manter o plugin padrão caching_sha2_password sempre que possível, pois ele oferece maior segurança criptográfica. Apenas em casos de compatibilidade com sistemas legados recorremos ao mysql_native_password. Além disso, para conexões remotas com caching_sha2_password, pode ser necessário configurar TLS ou usar o par de chaves RSA para a troca inicial de senha, especialmente se a conexão não for segura.

Verificando a Instalação / Testando a Configuração

Quer aprender na prática com especialistas?

A JRT Technology Solutions oferece treinamentos e implementação de MySQL para equipes corporativas.



Falar no WhatsApp

Thiago Paes Rodrigues

Com mais de 22 anos de experiência em Tecnologia da Informação, este profissional construiu uma trajetória sólida como empresário, atuando de forma estratégica na implementação de soluções tecnológicas que otimizam processos e impulsionam resultados em diferentes setores.