Datenbanken Aufruf sichern



  • Hallo,
    ich arbeite momentan an einem Datenbankprojekt (soll auf Windowsrechnern laufen). Hierfür verwende ich Java und die MySQL Connector API (5.1). Wenn ich versuche mich mit einer Datenbank zu verbinden führe ich folgenden Befehl aus:

    String URL; //Adresse der Datenbank
    String login_name;
    String password;
    
    Connection conn = DriverManager.getConnection(
         URL,
         login_name,
         password );
    

    Hierbei lese ich die URL, den Login und das Passwort aus einer Config-Datei aus, welche sich im selben Ordner, wie das Programm befindet.
    Nun soll das Projekt letztendlich von mehrere Personen verwendet werden. Dies ist dahingehend kein Problem, da sie sich, im Programm selber, anmelden müssen und so, somit im Programm selber, nur bestimmte Zugriffsrechte haben.

    Das Problem ist nun, dass man momentan einfach die Config-Datei öffnen kann und die Datenbank direkt ansprechen kann, wodurch sie Zugang auf alle Daten hätte.

    Die Frage ist also, wie übermittel ich den Programm die Daten (URL, Login, Passwort), sodass man sie immer noch verändern kann (ohne neu zu compelieren) und ermögliche gleichzeitig, dass nur bestimmte Benutzter die Datei lesen und bearbeiten können?
    Ich hatte überlegt das Programm mit hilfe eines C++-Programmes aufzurufen und die Daten als Parameter zu übergeben, da man, meines Wissens nach, die .exe eines C++-Programms nicht in Quellcode zurückwandeln kann (im Gegensatz zur .jar bei Java). Allerdings könnte man einfach ein eigenes Programm schreiben, dies durch das eigentliche Programm ersetzten um so die Daten auslesen. Daher weis ich momentan nicht, was ich machen könnte.

    Ich hoffe jemand kann mir helfen (es muss auch nicht 100% sicher sein, jedoch sichere als momentan).



  • Hi,

    von mir nur mal zwei Tips zur Sicherheit:
    1. das Passwort nicht direkt im Quelltext reinschreiben, sondern schrittweise bauen, z.B.
    Passwort = "-----"
    Passwort[ 4 ] = 28
    Passwort[ 1 ] = 36
    Passwort[ 5 ] = 29
    Passwort[ 3 ] = Passwort[ 1 ] - 7
    Passwort[ 2 ] = round( Wurzel aus Passwort[ 1 ] * Passwort[ 5 ] )
    Eventuell dazwischen noch was anderes machen, damit der Compiler das nicht wegoptimieren kann.
    2. Um zu verhindern, dass einfaches Rumprobieren und Rumspielen zum Ergebnis führt zusätzlich zu den übergebenen Parametern noch eine Kontrollsumme über die Parameter mit übergeben, damit das Programm testen kann ob die Parameter ordentlich übergeben sind oder nur durch ausprobieren zustande gekommen sind.

    Gruß Mümmel



  • Sowas wirst du nie sicher bekommen.
    Lass den Benutzer das Passwort für die Datenbank eingeben (und am besten die Passwörter koppeln, oder gleich single sign on verwenden).
    Oder lass dein Programm nicht direkt auf die Datenbank zugreifen, sondern über einen Application Server laufen, auf den die Benutzer keinen direkten Zugriff haben.



  • @win8789
    Ich nehme mal an die Benutzer der Anwendung sollen das Datenbank-Passwort nicht kennen, weil der Datenbank-User viel zu viel Rechte auf die DB hat - mehr als jeder einzelne Benutzer können soll. Falls ich damit falsch liege ist die Antwort ja trivial, wie Mechanics schon geschrieben hat: die Benutzer müssen das Datenbank-Passwort bei jedem Start eingeben.

    Ansonsten...

    Gratulation, du hast eines DER Standardprobleme von "zweischichtigen" Anwendungen entdeckt. Im übrigen auch einer der ganz grossen Klassiker wenn es um architekturelle Entscheidungen geht die oft getroffen werden ohne dass man weiss was man sich damit für Probleme einhandelt. Und die nachträglich natürlich nicht mehr mit vertretbarem Aufwand zu ändern sind.

    Echte Lösung dafür gibt es keine - ausser eben die Architektur der Anwendung zu ändern. Also z.B. eine 3. Schicht einziehen wie Mechanics auch schon vorgeschlagen hat.

    Bzw. kann man auch - je nachdem wie mächtig der SQL-Dialekt der DB ist - einen grossen Teil der Business-Logik in Stored-Procedures in der DB verschieben. So dass die DB selbst die nötigen "darf der das?" Checks durchführt.

    Wobei wenn du schreibst Java und MySQL ist vermutlich die Variante eine 3. Schicht einzuziehen sinnvoller. Wenn du sauber gearbeitet hast was Trennung von GUI Code und Business-Logik angeht und mit ein Bisschen Glück kann es sogar sein dass der Aufwand dafür ... "leistbar" ist.



  • hustbaer schrieb:

    Wobei wenn du schreibst Java und MySQL ist vermutlich die Variante eine 3. Schicht einzuziehen sinnvoller. Wenn du sauber gearbeitet hast was Trennung von GUI Code und Business-Logik angeht und mit ein Bisschen Glück kann es sogar sein dass der Aufwand dafür ... "leistbar" ist.

    Ok, danke. Prinzipiell habe ich jegliche Arbeit mit der Datenbank in Funktionen aufgeteilt, welche von den GUI-Elementen verwendet werden. Daher könnte ich eine Funktion umschreiben, solange sie immer noch das Selbe macht wie vorher.
    Werde mal sehen, was ich nun am besten machen sollte.

    Edit:
    Ein Beispiel wäre eine Funktion wie:

    static public String getUsername(Statement stmt, int ID) throws SQLException{
        String sql; //Erstelle SQL-Befehl
        ResultSet rs = stmt.executeQuery(sql); //Führe aus
    
        return rs.getString(1); //Lese Ergebnis aus
    }
    


  • Wenn diese Funktion direkt vom GUI Teil aufgerufen wird, dann ist das keine saubere Trennung. Schliesslich ist ein Parameter ein Statement Objekt (ich nehme an das JDBC Statement Interface?), und der GUI Teil sollte sich nicht dafür interessieren müssen wie und wo er zu diesem Statement Objekt kommt.

    Abgesehen davon bleibt die Frage wo die Business Logik implementiert ist.

    ----

    win8789 schrieb:

    Prinzipiell habe ich jegliche Arbeit mit der Datenbank in Funktionen aufgeteilt, welche von den GUI-Elementen verwendet werden. Daher könnte ich eine Funktion umschreiben, solange sie immer noch das Selbe macht wie vorher.

    Ich bin nicht sicher ob du den Vorschlag richtig verstanden hast.
    Es geht darum den ganzen Code der mit der DB kommuniziert plus der gesamten Business-Logik in ein getrenntes Programm rauszuziehen.

    Du hättest dann also ein System das aus drei Prozessen besteht: GUI, Application-Server und DB-Server.

    Dabei kommuniziert dann nur der Application-Server mit der Datenbank und die GUI plaudert nur mit dem Application-Server. Sämtliche wichtigen Regeln (wer darf was etc.) müssen im Application-Server umgesetzt oder zumindest überprüft werden.

    Den Zugriff auf den Application-Server von der GUI aus kannst du dann z.B. mittels RMI oder einem Web-Service Stack machen.

    ----

    Wenn du dann so ein System hast, dann muss nur noch der Application-Server das DB Passwort kennen. Und den kannst du auf einem geschützten System laufen lassen. Dadurch ist es dann kein Problem mehr wenn das Passwort einfach in einem Config-File steht, da die normalen User auf dieses System keinen vollen Zugriff haben, sondern sich nur mit dem Application-Server verbinden können. Und da der Application-Server sämtliche wichtigen Regeln implementiert bzw. prüft, ist das auch voll OK, selbst wenn jemand den GUI Client dekompiliert und irgendwelche Änderungen darin macht.

    ps: Die "moderne" Variante davon wäre dann statt eines klassischen GUI Client gleich ne Web-Anwendung zu machen.



  • hustbaer schrieb:

    ps: Die "moderne" Variante davon wäre dann statt eines klassischen GUI Client gleich ne Web-Anwendung zu machen.

    Jetzt schlag doch nicht gleich solche Teufeleien vor 😞