Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   INSERT kann mit einem Open ausgeführt werden? (https://www.delphipraxis.net/157640-insert-kann-mit-einem-open-ausgefuehrt-werden.html)

dust258 19. Jan 2011 13:27

Datenbank: Firebird • Version: 2.1 • Zugriff über: BDE

INSERT kann mit einem Open ausgeführt werden?
 
Ich arbeite an einem kleinen Modul für meine Applikation, die es dem User erlauben soll, kleine SQL-Statements (nur SELECT) zu schreiben um sich eigene Auswertungen anzeigen zu lassen.

Nach dem TQuery.Open werden die Ergebnisse dann in einem TDBGrid angezeigt. Das Problem ist, das der User einfach Insert oder Update-Befehle eigeben kann, und so die Daten manipuliert.

Nachdem z.B. ein INSERT-Statement mit open ausgefüht wurde, wird wie zu erwarten eine Exception ausgefüht (Keine Daten in der Datenbank).
Aber mit dem nächsten ExecSQL (welches ich im OnClose des Formulars aufrufe), wird das zuvor fehlerhaft ausgeführte SQL-Statement ausgeführt. (und die Daten in die Datenbank eingetragen).

Bei meinen Direkt-Komponenten (DevArt) hat mir folgende Lösung geholfen:
Delphi-Quellcode:
  try
    query.Open;
  except
    on e : Exception do
    begin
      query.Transaction.Rollback;
      MessageDLG(e.Message,mtError,[mbOK],0);
    end;
  end;
In der TQuery gibt es den Punkt Transaction aber nicht. Kennt Jemand von euch vielleicht das Problem?

Bernerbaer 19. Jan 2011 13:41

AW: INSERT kann mit einem Open ausgeführt werden?
 
Variante 1: Erstelle Views und lasse dem User nur auf diese zugreifen.

Variante 2: überprüfe vor dem Open den vom User zusammengestellten SQL-Syntax auf das Vorhandensein von alter, insert, update und verhindere die Ausführung wenn einer dieser Begriffe vorkommt.

DeddyH 19. Jan 2011 13:43

AW: INSERT kann mit einem Open ausgeführt werden?
 
Zu Variante 2: wieso nicht einfach nur SELECT als erstes Wort zulassen? Ansonsten müsste man auf jedes Wort achten, das zur Manipulation dient (CREATE und DROP fehlen in Deiner Auflistung z.B.)

taveuni 19. Jan 2011 13:45

AW: INSERT kann mit einem Open ausgeführt werden?
 
Ist das auch so wenn Du die Query dynamisch erzeugst?

Bernerbaer 19. Jan 2011 13:49

AW: INSERT kann mit einem Open ausgeführt werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1075800)
Zu Variante 2: wieso nicht einfach nur SELECT als erstes Wort zulassen?

weil ich viel zu weit gedacht habe (gleichzeitiges vorkommen von select und insert in einer Abfrage) und das Einfachste mir nicht in den Sinn gekommen ist.
Zitat:

Zitat von DeddyH (Beitrag 1075800)
Ansonsten müsste man auf jedes Wort achten, das zur Manipulation dient (CREATE und DROP fehlen in Deiner Auflistung z.B.)

stimmt!

Wobei ich persönlich doch die Variante 1 vorziehen würde mit den Views und einer sauberen Benutzerzugriffsregelung.

dust258 19. Jan 2011 14:10

AW: INSERT kann mit einem Open ausgeführt werden?
 
@taveuni: Ja, macht keinen Unterschied

Hab ich mir fast gedacht. Views kommen für mich leider nicht in Frage, da die Datenstruktur fehlt. Also werde ich wohl vor dem Open parsen.
@DeddyH: Die Idee ist super, nur leider sind in meinem Fall auch mehrere SQL-Befehle hintereinander möglich, daher werde ich wohl nach "verbotenen" Wörtern suchen. Hier meine Lösung:

Delphi-Quellcode:
function TListStatSchnittForm.SucheManipulativeAbfragen(inSSQLText: String): Boolean;
var
  lSSQLxStrings : String;
  lBInString : Boolean;
  i : integer;
begin
  Result := false;

  //Schlüsselwörter in Strings werden ignoriert
  lBInString := false;
  for I := 0 to Length(inSSQLText) - 1 do
  begin
    if (inSSQLText[i] = '"') then
      lBInString := not lBInString;
    if not lBInString then
      lSSQLxStrings := lSSQLxStrings + inSSQLText[i];
  end;

  if (pos('INSERT', Uppercase(lSSQLxStrings)) > 0) or
     (pos('UPDATE', Uppercase(lSSQLxStrings)) > 0) or
     (pos('DROP', Uppercase(lSSQLxStrings)) > 0) or
     (pos('CREATE', Uppercase(lSSQLxStrings)) > 0) or
     (pos('ALTER', Uppercase(lSSQLxStrings)) > 0) or
     (pos('DELETE', Uppercase(lSSQLxStrings)) > 0)
  then
  Result := true;
end;
Edit: Danke für die Hilfe ^^

joachimd 19. Jan 2011 15:38

AW: INSERT kann mit einem Open ausgeführt werden?
 
lass dies von der Datenbank überwachen: lege dazu einen User an, der nur lesend auf die entsprechenden Tabellen zugreifen darf. Logge dich für dein 'benutzer darf SQL eingeben' Fenster über eine zusätzliche Connection mit eben diesem User (oder einem frei zu wählenden) an. Falls dann der Admin Sch... baut und dem falschen Benutzer zuviele Rechte vergibt, ist es nicht mehr dir anzulasten;)

Valle 19. Jan 2011 17:47

AW: INSERT kann mit einem Open ausgeführt werden?
 
Hallo,

joachimd hat absolut Recht! Fange auf keine Fall an, solche Spielereien einzubauen!

Sofern ich deinen Code richtig verstanden habe, kann ich deinen Code mit einem einfachen Leerzeichen vor dem "INSERT" aushebeln. Daneben gibt es noch weitere Möglichkeiten wie GRANT oder SET PASSWORD.

Einen read-only Benutzer zu erstellen sollte vom Aufwand nur unwesentlich ins Gewicht fallen, ist in Sachen Sicherheit aber wohl am einfachsten und besten. Achte aber auch hier darauf, dass der Benutzer auch nur die Spalten lesen kann die er lesen darf. Willst du beispielsweise unterbinden, dass ein Nutzer Passwörter auslesen kann, indem du einfach nur die gewünschten Spalten in eine Tabelle ausgibst, so ist dies genauso einfach über SELECT password AS username zu erreichen. ;-)

Liebe Grüße,
Valentin

Sir Rufo 19. Jan 2011 20:03

AW: INSERT kann mit einem Open ausgeführt werden?
 
Wenn die Beschränkung reicht, dass nur eine Abfrage ausgeführt werden kann,
dann führe das einfach so aus:

Code:
query.SQL.Text := 'SELECT * FROM ( ' + Memo.Lines.Text + ' ) AS UserQuery';
Aber erkläre mir doch bitte mal, warum du beim FormClose ein ExecSQL ausführst?
Das macht in meinen Augen irgendwie keinen Sinn.

Und wieso dir eine Transaction da helfen soll, ist mir auch nicht klar.
Das scheint mir alles ein wenig am Thema vorbei ;)

dust258 20. Jan 2011 12:25

AW: INSERT kann mit einem Open ausgeführt werden?
 
@joachimd: Die Struktur ist leider vorgegeben (Das Programm arbeitet mit multiplen Datenbanken)

@Valle: Nein, ein einfaches "Leerzeichen vor dem "INSERT"" hebelt nichts aus

@Sir Rufo: Das würde die Befehle zu sehr einschränken. Und das ExecSQL wird im OnDestroy aufgerufen in einer Query der Benutzerkontensteuerung

Eine eigene Transaktion würde mein Problem sicher auch beheben...


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:06 Uhr.

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf