MySQL: Überprüfen Sie, ob der Benutzer vorhanden ist, und löschen Sie ihn

84

Es gibt keine Standardmethode, um zu überprüfen, ob ein MySQL-Benutzer vorhanden ist, und basierend darauf zu löschen. Gibt es dafür Problemumgehungen?

Bearbeiten: Ich brauche einen direkten Weg, um dies auszuführen, ohne einen Fehler auszulösen,
z

DROP USER test@localhost; :    
Cherian
quelle
1
Meinen Sie einen MySQL-Benutzer? Oder ein Benutzerdatensatz, den Sie in einer Tabelle in MySQL speichern?
Jason Cohen
Es sieht so aus, als hätte MariaDB diese Funktion: mariadb.com/kb/en/mariadb/drop-user
Limited Atonement
1
Für zukünftige Leser: MySQL 5.7 hat die Funktion 'DROP USER IF EXISTS', siehe stackoverflow.com/questions/598190/…
Andrei Epure
1
@AndreiEpure Wenn Sie dies nur als Antwort setzen könnten, werde ich es als die richtige markieren.
Cherian

Antworten:

87

Das hat bei mir funktioniert:

GRANT USAGE ON *.* TO 'username'@'localhost';
DROP USER 'username'@'localhost';

Dadurch wird der Benutzer erstellt, sofern er noch nicht vorhanden ist (und ihm ein harmloses Privileg gewährt), und dann in beide Richtungen gelöscht. Hier finden Sie eine Lösung: http://bugs.mysql.com/bug.php?id=19166

Updates: @Hao empfiehlt das Hinzufügen IDENTIFIED BY; @andreb (in Kommentaren) schlägt die Deaktivierung vor NO_AUTO_CREATE_USER.

Behandle deine Mods gut
quelle
5
In der MySQL Grant-Handbuchseite heißt es tatsächlich: VERWENDUNG: Synonym für "keine Privilegien"
stivlo
6
Dies ist keine Option mehr. :( Die aktuelle Version von MySQL erstellt keinen neuen Benutzer mehr für die GRANT-Anweisung. Es war eine "Funktion", die sie hinzugefügt haben .;) Sieht so aus, als ob Cherians Option die einzige ist, die derzeit funktioniert.
GazB
1
@ Zasurus. dev.mysql.com/doc/refman/5.1/en/grant.html (auch 5.5 und 5.6) scheint darauf hinzudeuten , dass Sie falsch liegen. Es gibt die Option "Kein automatischer Benutzer erstellen". Sofern ich das Handbuch nicht falsch verstehe, bedeutet dies, dass durch die Gewährung ein Benutzer erstellt wird, wenn dieser nicht vorhanden ist.
Andre
@andreb Vielleicht war die Option "NO_AUTO_CREATE_USER" aktiviert, als ich dies versuchte oder standardmäßig (wie in Ich habe es nicht geändert). Wenn ich Zeit habe, werde ich dies versuchen, um diese Option auszuschalten und es erneut zu versuchen. Es gibt ein paar offene Fehlerberichte mit dieser Option, vielleicht ist einer davon auch das Problem. :)
GazB
Siehe auch die Antwort von @ Hao. Ich brauchte das IDENTIFIED BY, damit das tatsächlich funktioniert.
Matthew
14

Auf die Antwort von Phyzome (die am höchsten bewertete) scheint es mir, dass der Benutzer automatisch erstellt wird, wenn Sie am Ende der Bewilligungserklärung "identifiziert durch" einfügen. Wenn Sie dies nicht tun, wird der Benutzer nicht erstellt. Der folgende Code funktioniert für mich:

GRANT USAGE ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
DROP USER 'username'@'localhost';

Hoffe das hilft.

Hao
quelle
Ich hatte einige alte Skripte ohne das IDENTIIFIED BY 'Passwort'; Teil, der am 5.6 gearbeitet hat. Aber nicht am 5.7. Das Hinzufügen des Teils IDENTIFIED BY 'password' hat mir geholfen.
Joensson
13

Die Antwort darauf fand ich in einem der MySQL-Foren. Wir müssen eine Prozedur verwenden, um den Benutzer zu löschen.

Benutzer hier ist "test" und "databaseName" der Datenbankname.


SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI';
USE databaseName ;
DROP PROCEDURE IF EXISTS databaseName.drop_user_if_exists ;
DELIMITER $$
CREATE PROCEDURE databaseName.drop_user_if_exists()
BEGIN
  DECLARE foo BIGINT DEFAULT 0 ;
  SELECT COUNT(*)
  INTO foo
    FROM mysql.user
      WHERE User = 'test' and  Host = 'localhost';
   IF foo > 0 THEN
         DROP USER 'test'@'localhost' ;
  END IF;
END ;$$
DELIMITER ;
CALL databaseName.drop_user_if_exists() ;
DROP PROCEDURE IF EXISTS databaseName.drop_users_if_exists ;
SET SQL_MODE=@OLD_SQL_MODE ;

CREATE USER 'test'@'localhost' IDENTIFIED BY 'a'; GRANT ALL PRIVILEGES ON databaseName.* TO 'test'@'localhost' WITH GRANT OPTION

Cherian
quelle
Danke @Cherian Ich bin mir nicht sicher, ob dies 2017 immer noch der beste Weg ist, aber zumindest ein Weg nach vorne! Ich kann nicht glauben, dass das immer noch so schwer ist ...
JMac
Nur zu Ihrer Information, Sie sollten immer die URL Ihrer Quelle angeben (zB: Die Antwort wurde von einem der MySQL- Formulare gefunden. Oder von einem der MySQL-Formulare (Quelle hier)
4
DROP USER IF EXISTS 'user'@'localhost' ;

das funktioniert bei mir ohne fehler in Maria DB zu werfen, es sollte auch bei dir funktionieren

Sathish Neel
quelle
2
Sicher unter MySQL 5.7 und höher. ... Zum Glück ist die neueste Version, die wir hier verwenden, 5.5.
Tetsujin
4

Update: Ab MySQL 5.7 können Sie DROP USER IF EXISTSAnweisungen verwenden. Ref: https://dev.mysql.com/doc/refman/5.7/en/drop-user.html

Syntax: DROP USER [IF EXISTS] user [, user] ...

Beispiel: DROP USER IF EXISTS 'jeffrey'@'localhost';

Zu Ihrer Information (und für ältere Versionen von MySQL) ist dies eine bessere Lösung ... !!!

Der folgende SP hilft Ihnen, Benutzer 'tempuser'@'%'durch Ausführen zu entfernenCALL DropUserIfExistsAdvanced('tempuser', '%');

Wenn Sie alle Benutzer entfernen genannt 'tempuser'(sagen wir 'tempuser'@'%', 'tempuser'@'localhost'und 'tempuser'@'192.168.1.101') ausführen SP wie CALL DropUserIfExistsAdvanced('tempuser', NULL);diese Weise werden alle Benutzer namens löschen tempuser!!! Ernsthaft...

Schauen Sie sich jetzt bitte das erwähnte SP an DropUserIfExistsAdvanced:

DELIMITER $$

DROP PROCEDURE IF EXISTS `DropUserIfExistsAdvanced`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `DropUserIfExistsAdvanced`(
    MyUserName VARCHAR(100)
    , MyHostName VARCHAR(100)
)
BEGIN
DECLARE pDone INT DEFAULT 0;
DECLARE mUser VARCHAR(100);
DECLARE mHost VARCHAR(100);
DECLARE recUserCursor CURSOR FOR
    SELECT `User`, `Host` FROM `mysql`.`user` WHERE `User` = MyUserName;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET pDone = 1;

IF (MyHostName IS NOT NULL) THEN
    -- 'username'@'hostname' exists
    IF (EXISTS(SELECT NULL FROM `mysql`.`user` WHERE `User` = MyUserName AND `Host` = MyHostName)) THEN
        SET @SQL = (SELECT mResult FROM (SELECT GROUP_CONCAT("DROP USER ", "'", MyUserName, "'@'", MyHostName, "'") AS mResult) AS Q LIMIT 1);
        PREPARE STMT FROM @SQL;
        EXECUTE STMT;
        DEALLOCATE PREPARE STMT;
    END IF;
ELSE
    -- check whether MyUserName exists (MyUserName@'%' , MyUserName@'localhost' etc)
    OPEN recUserCursor;
    REPEAT
        FETCH recUserCursor INTO mUser, mHost;
        IF NOT pDone THEN
            SET @SQL = (SELECT mResult FROM (SELECT GROUP_CONCAT("DROP USER ", "'", mUser, "'@'", mHost, "'") AS mResult) AS Q LIMIT 1);
            PREPARE STMT FROM @SQL;
            EXECUTE STMT;
            DEALLOCATE PREPARE STMT;
        END IF;
    UNTIL pDone END REPEAT;
END IF;
FLUSH PRIVILEGES;
END$$

DELIMITER ;

Verwendung:

CALL DropUserIfExistsAdvanced('tempuser', '%'); Benutzer entfernen 'tempuser'@'%'

CALL DropUserIfExistsAdvanced('tempuser', '192.168.1.101'); Benutzer entfernen 'tempuser'@'192.168.1.101'

CALL DropUserIfExistsAdvanced('tempuser', NULL);entfernen Sie alle Benutzer benannt 'tempuser'(z. B. sagen 'tempuser'@'%', 'tempuser'@'localhost'und 'tempuser'@'192.168.1.101')

Rajukoyilandy
quelle
3

Ähm ... Warum all die Komplikationen und Tricks?

Verwenden Sie stattdessen DROP USER ... Sie können den Benutzer einfach aus der Tabelle mysql.user löschen (die keinen Fehler auslöst, wenn der Benutzer nicht vorhanden ist) und dann die Berechtigungen löschen, um die Änderung zu übernehmen.

DELETE FROM mysql.user WHERE User = 'SomeUser' AND Host = 'localhost';
FLUSH PRIVILEGES;

- UPDATE -

Ich lag falsch. Es ist nicht sicher, den Benutzer so zu löschen. Sie müssen DROP USER verwenden. Da es möglich ist, MySQL-Optionen so einzustellen, dass Benutzer nicht automatisch über Zuschüsse erstellt werden (eine Option, die ich verwende), würde ich diesen Trick immer noch nicht empfehlen. Hier ist ein Ausschnitt aus einer gespeicherten Prozedur, die für mich funktioniert:

DECLARE userCount INT DEFAULT 0;
SELECT COUNT(*) INTO userCount FROM mysql.user WHERE User = userName AND Host='localhost';
IF userCount > 0 THEN
    SET @S=CONCAT("DROP USER ", userName, "@localhost" );
    PREPARE stmt FROM @S;
    EXECUTE stmt;
    SELECT CONCAT("DROPPED PRE-EXISTING USER: ", userName, "@localhost" ) as info;
END IF;
FLUSH PRIVILEGES;
BuvinJ
quelle
Teilen Sie mit, warum es "nicht sicher" ist ...? Sicher für wen auf welche Weise?
Dagelf
Nun, da ich dies vor mehr als einem Jahr gepostet habe, werde ich nicht behaupten, mich zu 100% an das zu erinnern, worauf ich mich bezog. Ich bin mir ziemlich sicher, dass ich damit gemeint habe, dass es den Benutzer nicht zuverlässig aus dem System entfernt. Ich denke, DROP USER leistet mehr als nur das Entfernen einer Zeile aus der Tabelle mysql.user. Entschuldigung, ich kann mir nicht vorstellen, was diese Details jetzt sind!
BuvinJ
Wenn ich raten würde, würde ich sagen, dass die Berechtigungsdatensätze nicht entfernt werden, sondern "verwaist" werden? (Abhängig von Ihren Einstellungen?)
BuvinJ
2

In Bezug auf die Antwort von @ Cherian können die folgenden Zeilen entfernt werden:

SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI';
...
SET SQL_MODE=@OLD_SQL_MODE;
...

Dies war ein Fehler vor 5.1.23. Nach dieser Version werden diese nicht mehr benötigt. Aus Gründen der Bequemlichkeit beim Kopieren und Einfügen ist hier dasselbe mit den oben entfernten Zeilen entfernt. Wiederum ist beispielsweise "Test" der Benutzer und "Datenbankname" die Datenbank; und das war von diesem Fehler .

DROP PROCEDURE IF EXISTS databaseName.drop_user_if_exists ;
DELIMITER $$
CREATE PROCEDURE databaseName.drop_user_if_exists()
BEGIN
  DECLARE foo BIGINT DEFAULT 0 ;
  SELECT COUNT(*)
  INTO foo
    FROM mysql.user
      WHERE User = 'test' and  Host = 'localhost';
   IF foo > 0 THEN
         DROP USER 'test'@'localhost' ;
  END IF;
END ;$$
DELIMITER ;
CALL databaseName.drop_user_if_exists() ;
DROP PROCEDURE IF EXISTS databaseName.drop_users_if_exists ;

CREATE USER 'test'@'localhost' IDENTIFIED BY 'a';
GRANT ALL PRIVILEGES  ON databaseName.* TO 'test'@'localhost'
 WITH GRANT OPTION
j4w7
quelle
2

Ich habe dieses Verfahren geschrieben, inspiriert von Cherians Antwort. Der Unterschied besteht darin, dass in meiner Version der Benutzername ein Argument der Prozedur ist (und nicht fest codiert ist). Ich mache auch ein sehr notwendiges FLUSH PRIVILEGES, nachdem ich den Benutzer fallen gelassen habe.

DROP PROCEDURE IF EXISTS DropUserIfExists;
DELIMITER $$
CREATE PROCEDURE DropUserIfExists(MyUserName VARCHAR(100))
BEGIN
  DECLARE foo BIGINT DEFAULT 0 ;
  SELECT COUNT(*)
  INTO foo
    FROM mysql.user
      WHERE User = MyUserName ;
   IF foo > 0 THEN
         SET @A = (SELECT Result FROM (SELECT GROUP_CONCAT("DROP USER"," ",MyUserName,"@'%'") AS Result) AS Q LIMIT 1);
         PREPARE STMT FROM @A;
         EXECUTE STMT;
         FLUSH PRIVILEGES;
   END IF;
END ;$$
DELIMITER ;

Ich habe diesen Code auch auf der CodeReview-Website veröffentlicht ( /codereview/15716/mysql-drop-user-if-exists ).

MadSeb
quelle
2
DROP USER 'user'@'localhost';

Mit dem obigen Befehl wird der Benutzer aus der Datenbank entfernt. Es ist jedoch wichtig zu wissen, ob derselbe Benutzer die Datenbank bereits verwendet. Diese Sitzung wird erst beendet, wenn der Benutzer diese Sitzung schließt. Es ist wichtig zu beachten, dass abgelegte Benutzer NOCH auf die Datenbank zugreifen und alle Vorgänge ausführen. Wenn Sie den Benutzer fallen lassen, wird die aktuelle Benutzersitzung nicht fallen gelassen

Prabhakar Undurthi
quelle
0

Durch die Kombination der Antwort von Phyzome (die bei mir nicht sofort funktioniert hat) mit dem Kommentar von andreb (was erklärt, warum dies nicht der Fall war) erhielt ich diesen scheinbar funktionierenden Code, der den NO_AUTO_CREATE_USER-Modus vorübergehend deaktiviert, wenn er aktiv ist:

set @mode = @@SESSION.sql_mode;
set session sql_mode = replace(replace(@mode, 'NO_AUTO_CREATE_USER', ''), ',,', ',');
grant usage on *.* to 'myuser'@'%';
set session sql_mode = @mode;
drop user 'myuser'@'%';
Svullo
quelle
0

im Terminal tun:

sudo mysql -u root -p

Geben Sie das Passwort ein.

select user from mysql.user;

Löschen Sie nun den Benutzer 'the_username'.

DROP USER the_unername;

Ersetzen Sie 'the_username' durch den Benutzer, den Sie löschen möchten.

Messou
quelle
-1

Falls Sie einen Schulserver haben, auf dem die Schüler viel gearbeitet haben. Sie können das Chaos einfach aufräumen, indem Sie:

delete from user where User != 'root' and User != 'admin';
delete from db where User != 'root' and User != 'admin';

delete from tables_priv;
delete from columns_priv;

flush privileges;
Jan.
quelle
-6

Wenn Sie meinen, dass Sie einen Drop aus einer Tabelle löschen möchten, falls vorhanden, können Sie den folgenden DELETEBefehl verwenden:

 DELETE FROM users WHERE user_login = 'foobar'

Wenn keine Zeilen übereinstimmen, ist dies kein Fehler.

Jason Cohen
quelle
2
Ich denke, das OP bezieht sich auf einen echten Datenbankbenutzer.
Tomalak
6
Dies ist die einfachste Lösung IMO. Benötigt nur korrektes SQL: DELETE FROM mysql.user WHERE user = 'foobar'
John Rix