Resumo : neste tutorial, você aprenderá sobre o controle de acesso a objetos armazenados no MySQL.
No MySQL, programas armazenados, incluindo procedimentos armazenados , funções armazenadas , gatilhos e eventos, são executados dentro de um contexto de segurança que determina seus privilégios.
Usos DEFINER
e SQL SECURITY
características do MySQL para controlar esses privilégios.
O atributo DEFINER
Ao definir uma rotina armazenada, como um procedimento armazenado ou função, você pode opcionalmente especificar o DEFINER
atributo, que é o nome de uma conta MySQL:
CREATE [DEFINER=user] PROCEDURE spName(parameter_list)
...
CREATE [DEFINER=user] FUNCTION sfName()
...
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Se você ignorar o DEFINER
atributo, o padrão será a conta do usuário atual.
Você pode especificar qualquer conta no DEFINER
atributo se tiver o privilégio SUPER
ou SET_USER_ID
. Se você especificar uma conta de usuário que não existe, o MySQL emitirá um aviso.
A partir do MySQL 8.0.16, você deve ter o SYSTEM_USER
privilégio para definir o DEFINER
atributo de um objeto armazenado para uma conta de usuário que tenha o SYSTEM_USER
privilégio.
A característica SQL SECURITY
Rotinas armazenadas (procedimentos e funções armazenados) e visualizações podem incluir uma SQL SECURITY
cláusula com um valor de DEFINER
ou INVOKER
:
CREATE [DEFINER=user] PROCEDURE spName(parameter_list)
SQL SECURITY [DEFINER | INVOKER]
...
CREATE [DEFINER=user] FUNCTION sfName(parameter_list)
SQL SECURITY [DEFINER | INVOKER]
...
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
DEFINTOR DE SEGURANÇA SQL
Quando você usa o SQL SECURITY DEFINER
para um objeto armazenado, ele será executado em um contexto de segurança do definidor com o privilégio do usuário especificado pelo DEFINER
atributo.
Observe que o usuário que invoca o objeto armazenado (ou invocador) pode não ter o mesmo privilégio que o definidor.
Caso o invocador tenha menos privilégios e o definidor tenha mais privilégios, o invocador pode realizar operações acima de seu privilégio dentro do objeto armazenado.
INVOCADOR DE SEGURANÇA SQL
Se você usar o SQL SECURITY INVOKER
para uma rotina ou visualização armazenada, ele operará dentro dos privilégios do invocador.
O DEFINER
atributo não tem efeito durante a execução do objeto.
Exemplo de controle de acesso a objetos armazenados
Primeiro, crie um novo banco de dados chamado testdb
:
CREATE DATABASE testdb;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Segundo, selecione o banco de dados testdb
com o qual trabalhar:
USE testdb;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Terceiro, crie uma nova tabela chamada messages
:
CREATE TABLE messages (
id INT AUTO_INCREMENT,
message VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
);
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Quarto, crie um procedimento armazenado que insira uma nova linha na messages
tabela:
DELIMITER $$
CREATE DEFINER = root@localhost PROCEDURE InsertMessage(
msg VARCHAR(100)
)
SQL SECURITY DEFINER
BEGIN
INSERT INTO messages(message)
VALUES(msg);
END$$
DELIMITER ;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Neste procedimento armazenado, o definidor é root@localhost
o superusuário que possui todos os privilégios.
A Segurança SQL está definida para o definidor. Isso significa que qualquer conta de usuário que chamar este procedimento armazenado será executada com todos os privilégios do definidor, ou seja, root@localhost
conta de usuário.
Quinto, crie um novo usuário chamado dev@localhost
:
CREATE USER dev@localhost
IDENTIFIED BY 'Abcd1234';
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Sexto, conceda o EXECUTE
privilégio dev@localhost
para que ele possa executar qualquer procedimento armazenado no testdb
banco de dados:
GRANT EXECUTE ON testdb.*
TO dev@localhost;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Sétimo, use dev@localhost
para fazer login no servidor MySQL:
mysql -u dev@localhost -p
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Oito, use SHOW DATABASES
para exibir o banco de dados que dev@localhost
pode acessar:
mysql> show databases;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Aqui está a lista:
+--------------------+
| Database |
+--------------------+
| information_schema |
| testdb |
+--------------------+
2 rows in set (0.00 sec)
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Nono, selecione o testdb
banco de dados:
mysql> use testdb;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Décimo, chame o InsertMessage
procedimento para inserir uma linha na messages
tabela:
mysql> call InsertMessage('Hello World');
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Esta é a saída:
Query OK, 1 row affected (0.01 sec)
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Mesmo dev@localhost
não tendo nenhum privilégio na messages
tabela, ele pode inserir uma nova linha nessa tabela com êxito por meio do procedimento armazenado porque o procedimento armazenado é executado no contexto de segurança da root@localhost
conta do usuário.
Décimo primeiro, vá para a sessão raiz e crie um procedimento armazenado que atualize a messages
tabela:
DELIMITER $$
CREATE DEFINER=root@localhost
PROCEDURE UpdateMessage(
msgId INT,
msg VARCHAR(100)
)
SQL SECURITY INVOKER
BEGIN
UPDATE messages
SET message = msg
WHERE id = msgId;
END$$
DELIMITER ;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Possui UpdateMessage
o contexto de segurança de INVOKER
quem chama esse procedimento armazenado.
Décimo segundo, vá para a dev@localhost
sessão do e chame o UpdateMessage()
procedimento armazenado:
mysql> call UpdateMessage(1,'Good Bye');
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Desta vez, o UpdateMessage()
procedimento armazenado é executado com os privilégios do chamador, que é dev@localhost
.
Por dev@localhost
não possuir nenhum privilégio na messages
tabela, o MySQL emite um erro e rejeita a atualização:
ERROR 1142 (42000): UPDATE command denied to user 'dev'@'localhost' for table 'messages'
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Neste tutorial, você aprendeu sobre o controle de acesso a objetos armazenados do MySQL.