Sonderzeichen Probleme beim Auslesen aus mySQL Datenbank + Problem bei Integer auslesen

  • Antworten:20
Alexej D.
  • Forum-Beiträge: 10

09.02.2014, 21:58:32 via Website

Hallo zusammen,

dank des Forums habe ich echt schon eine Menge gelernt. Nach dem ich erfolglos probiert habe über JDBC-Treiber eine Datenbankverbindung aufzubauen, habe ich den einen Rat aus dem Forums befolgt und einen kleinen PHP-Webserver geschrieben, der die Datenbankverbindung für mich erstellt. Da ich dabei jedoch auf viele Codefragmente von Onkel Google zurückgegriffen habe, funktioniert alles noch nicht so wie ich es mir wünsche.
Ich schaffe es zwar Strings aus meiner Datenbank auszulesen aber leider werden hier die Sonderzeichen nicht bzw. durch Fragezeichen dargestellt.
Ich versuche seit heute morgen einige Ratschläge aus dem Internet umzusetzen aber ohne Erfolg. Ich hoffe jemand kann mir weiterhelfen.

1. Datenbank Kollation auf UTF-8 gesetzt
2. in meiner php folgende Abfrage als erstes durchführen
1mysql_query("SET character_set_results = 'utf8', character_set_client = 'utf8', character_set_connection = 'utf8', character_set_database = 'utf8', character_set_server = 'utf8'", $conn);
3. php-file in UTF-8 mit und ohne BOM konvertieren

Wenn ich das PHP-Skript in ANSI konvertiere, bekomme ich über den Webbrowser die richtigen Sonderzeichen also ä,ü,ä zurück, konvertiere ich in UTF-8 bekomme ich schwarze Rauten mit Fragezeichen, die auch über meine Emuator in Eclipse angezeigt werden.
Ich würde daher meine PHP-File in ANSI kovervieren und vermute, dass ich im JAVA Code noch eine konvertierung durchführen muss.

meine PHP-File sieht folgendermaßen aus:
1<?php
2$con=mysqli_connect("localhost","dbuser","pw","dbname");
3if (mysqli_connect_errno($con))
4{
5 echo "Failed to connect to MySQL: " . mysqli_connect_error();
6}
7$id = $_GET['id'];
8$spalte = $_GET['spalte'];
9mysql_query("SET character_set_results = 'utf8', character_set_client = 'utf8', character_set_connection = 'utf8', character_set_database = 'utf8', character_set_server = 'utf8'", $conn);
10
11$result = mysqli_query($con,"SELECT $spalte FROM Daten where ID='$id'");
12$row = mysqli_fetch_array($result);
13$data = $row[0];
14if($data){
15echo $data;
16}
17mysqli_close($con);
18?>



folgenden JAVA-Code nutze ich zum parsen:
1protected static String getSpalteDBnachID (int id, String spalte) {
2
3 try{
4
5 String link = "domain/skript.php?id="+id+"&spalte="+spalte;
6 URL url = new URL(link);
7 HttpClient client = new DefaultHttpClient();
8 HttpGet request = new HttpGet();
9 request.setURI(new URI(link));
10 HttpResponse response = client.execute(request);
11 BufferedReader in = new BufferedReader
12 (new InputStreamReader(response.getEntity().getContent()));
13
14 StringBuffer sb = new StringBuffer("");
15 String line="";
16 while ((line = in.readLine()) != null) {
17 sb.append(line);
18 break;
19 }
20 in.close();
21 return sb.toString();
22 }catch(Exception e){
23 return new String("Exception: " + e.getMessage());
24 }
25 }
Der Wert dieser Funktion soll dann als Textview uasgegeben werden.


Ein anderes Problem habe ich bei einer anderen Funktion die einen Integer aus der Datenbank lesen soll:
1protected static int maxId() {
2
3 try{
4
5 String link = "Domain/maxid.php";
6 URL url = new URL(link);
7 HttpClient client = new DefaultHttpClient();
8 HttpGet request = new HttpGet();
9 request.setURI(new URI(link));
10 HttpResponse response = client.execute(request);
11 BufferedReader in = new BufferedReader
12 (new InputStreamReader(response.getEntity().getContent()));
13
14
15 StringBuilder sb = new StringBuilder();
16 String line = null;
17 while ((line = in.readLine()) != null) {
18 sb.append(line);
19
20 break;
21 }
22 in.close();
23 return sb //-------------------------------------------------------------------------------> hier bekomme ich einen Fehler. Wie schaffe ich es als Rückgabewert ein Integer zu liefern.
24 }catch(Exception e){
25 //return null;
26 }
27 }
Das PHP-Skript liefert einen Integer aber ich schaffe es nicht aus sb einen Integer auszulesen. Oder gibt es statt StringBuildner die Möglichkeit einen IntegerBuildner zu benutzen?


Ich würde mich sehr freuen wenn ihr mir weiterhelfen könntet.
Viele Grüß
Alex

— geändert am 09.02.2014, 22:11:01

Antworten
Gelöschter Account
  • Forum-Beiträge: 271

09.02.2014, 22:28:47 via App

In Zeile 2 im PHP Script wird $con definiert, in Zeile 9 wird $conn abgefragt

Nexus 4 - 5.1 Stock Root

Antworten
Alexej D.
  • Forum-Beiträge: 10

10.02.2014, 00:33:22 via Website

Danke für die schnelle Antwort.
Leider werden die Sonderzeichen immer noch nicht richtig dargestellt aber ich bin echt beeindruckt dass du das gesehen hast. Hatte den Code heute stundenlang vor Augen und das ist mir nicht aufgefallen. Gibt es da vllt ein Trick oder Hilfsprogramm, dass so etwas erkennt?


Ich habe außerdem noch an meinem zweiten Problem gearbeitet mit der Umwandlung von String zu Int.
Ich habe den alten Code geändert und gebe nun die maxID als String zurück.
Dann parse ich durch
1int maxidint = Integer.parseInt(maxID)
Dabei stürzt meine APP jedoch ab und gibt mir den Fehler aus: Caused by: java.lang.NumberFormatException: unable to parse '3' as integer
Woran kann das liegen bzw. wie behebe ich das Problem? Ein selbsterstellter String ala "123" wird ohne Probleme geparst.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

10.02.2014, 05:00:51 via App

Vlt sind im String noch leerzeichen drin
Trimm diesen und Versuche es erneut.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Markus B.
  • Forum-Beiträge: 636

10.02.2014, 11:04:21 via Website

Hallo,
schau mal nach mit was für einem encoding deine Datenbank arbeitet (http://dev.mysql.com/doc/refman/5.7/en/charset-show.html).
Des Weiteren ließ dir mal was zum Thema sql injection durch. Das was du da in deinem php-Teufelszeug-Skript machst ist gefährlich.

Gruß,
Markus

Antworten
Alexej D.
  • Forum-Beiträge: 10

10.02.2014, 15:25:26 via Website

Danke Pascal und Markus.
@ Pascal: habe das String to Int Problem lösen können. Anscheinend war wirklich ein zusätzliches Byte vor der Zahl. Durch Konvertierung der maxID.php zu ANSI funktioniert das parsen jetzt ohne Probleme.

@Markus:
Wie genau überprüfe ich das? Ich habe es mit SHOW COLLATION versucht und eine ellenlange Liste bekommen mit möglichen Kollationen. Ich habe den entsprechenden Spalten aber bereits die Kollation utf8_general_mysql500_ci bzw. utf8_general_ci zugewiesen.

Zur SQL Injection habe ich schon etwas gelesen. Ich habe gedacht, dass ich mit dem php-Webserver schon etwas sicherer unterwegs bin als wenn ich es über einen JDBC Treiber versuchen würde.
Meine Überlegung war außerdem, dass ich mir um SQL-Injection keine Sorge machen brauch, wenn ich nur im Programmcode generierte Variablen per GET schicke und den Nutzer so keine Möglichkeit gebe selber Eingaben also SQL-Injections durchzuführen.
Oder ist es möglich die genutzte PHP-Datei auszulesen, sodass man über einen Browser eine SQL-Injection durchführen kann?


Nochmal zurück zu der anfänglichen Frage bzgl. der Sonderzeichen. Da mir meine PHP-Datei im Browser auf dem Computer, nun die Sonderzeichen ohne Probleme ausgibt, vermute ich, dass ich ein encoding im JAVA-Code vornehmen muss. Ich hoffe jemand fällt noch eine mögliche Lösung zu meinem Problem ein. Ansonsten bedanke ich mich nocheinmal vielmals für eure Hilfe.

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

10.02.2014, 15:30:36 via Website

Alexej D.


Zur SQL Injection habe ich schon etwas gelesen. Ich habe gedacht, dass ich mit dem php-Webserver schon etwas sicherer unterwegs bin als wenn ich es über einen JDBC Treiber versuchen würde.
Meine Überlegung war außerdem, dass ich mir um SQL-Injection keine Sorge machen brauch, wenn ich nur im Programmcode generierte Variablen per GET schicke und den Nutzer so keine Möglichkeit gebe selber Eingaben also SQL-Injections durchzuführen.
Oder ist es möglich die genutzte PHP-Datei auszulesen, sodass man über einen Browser eine SQL-Injection durchführen kann?



Jemand könnte auf die Idee kommen und das an die PHP Datei übergebene ID manuell gegen sowas wie das hier auszutauschen:
'
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--

lg Voss

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

10.02.2014, 16:02:26 via Website

Genau deshalb braucht man einen Passwortschutz

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Markus B.
  • Forum-Beiträge: 636

10.02.2014, 16:08:09 via App

Hi,
auch ein Passwort schützt da nicht ... Das standard Verfahren sind prepared statments mit named Parametern. Dann werden Daten und Statement getrennt und der DB Treiber über nimmt das sichere escapen. Dieser berücksichtigt dann auch das encoding der Daten.
Zu der Liste, welche du bekommst, ließ in dem Dokument noch ein bissel mehr und du wirst verstehen.

— geändert am 10.02.2014, 16:10:27

Antworten
Alexej D.
  • Forum-Beiträge: 10

10.02.2014, 16:41:16 via Website

Und nochmals ein dickes Danke an alle für die vielen Antworten.

Ich sollte mich scheinbar wirklich nochmal mit dem Thema Sicherheit auseinandersetzen.

@Markus
Ok ich versuche es. Problem ist nur Englisch ist nicht gerade meine Stärke :P
Ich vermute auch, dass es nicht nur an der Formatierung der Datenbank liegt, da mein Browser (Firefox) mir die die Umlaute richtig darstellt.
Nur Eclipse hat Probleme beim Auslesen.
Ich habe bei Google schon zig Threads gelesen und z.B. folgendes im JAVA -Code bei mir verändert
1BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
weil ich gehofft habe so die Information die meine APP vom PHP-Skript bekommt, auf UTF-8 zu konvertieren zu können. Leider ohne Erfolg.

Gibt es vllt noch die Möglichkeit irgendwo in diesem Code ein Encoding hinzuzufügen?
1StringBuffer sb = new StringBuffer("");
2 String line="";
3 while ((line = in.readLine()) != null) {
4 sb.append(line);

Oder liegt es wirklich nur an den Einstellungen meiner Datenbank?

Viele Grüße
Alex

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

10.02.2014, 16:44:01 via Website

Wieso sollte ein Passwort nicht schützen solange man es nicht mit snifft?
einfach das PW mitschicken und im php erst überprüfen ob das PW stimmt und dann erst alle anderen Parameter und die DB Operationen berücksichtigen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Markus B.
  • Forum-Beiträge: 636

10.02.2014, 16:47:48 via App

Also lässt du deine Haustür auch offen und stellst einen Typen davor damit niemand rein kann ?
Deine Lösung setzt dann auch eine https-Verbindung voraus ...
Mal ganz davon abgesehen das du gleich mitlieferst wie einfach es ist deinen Weg auszuhebeln 😁
Symmetrische Verfahren machen in diesem Kontext meiner Meinung nach keinen Sinn.

— geändert am 10.02.2014, 17:00:57

impjorPascal P.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

10.02.2014, 17:10:17 via Website

Jetzt habe ichs verstanden
Danke Markus

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Markus B.
  • Forum-Beiträge: 636

10.02.2014, 17:25:32 via Website

Pascal P.
Jetzt habe ichs verstanden
Danke Markus

Das freut mich :)

So weiter im Kontext:
Was gibt dir denn folgende Abfrage zurück:
SELECT default_character_set_name FROM information_schema.SCHEMATA S
WHERE schema_name = "<DEIN-SCHEMANAME>";

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

10.02.2014, 17:27:23 via Website

1. Bin nicht so gut in SQL
2. ich bin nicht der Fragesteller und muss im Moment keine DB betreiben

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Markus B.
  • Forum-Beiträge: 636

10.02.2014, 17:30:38 via Website

Pascal P.
1. Bin nicht so gut in SQL
2. ich bin nicht der Fragesteller und muss im Moment keine DB betreiben

Das war auch an Alexej D. gerichtet.

Antworten
Alexej D.
  • Forum-Beiträge: 10

11.02.2014, 13:14:54 via Website

Hallo zusammen, entschuldigt die späte Antwort und danke Markus für den SQL-Befehl.

Ich habe ihn ausgeführt und default_character_set_name: latin1 bekommen

Ich habe daher sofort versucht die Kollation auf utf8 zu ändern und wenn ich deinen Code jetzt eingebe, bekomme ich als default_character_set_name: utf8
die Sonderzeichen werden aber immer noch nicht richtig dargestellt.

Ich habe es dann bei einem anderen Datenbankanbieter probiert und siehe da es funktioniert ...

Leider ist die Datenbankverbindung bei dem Anbieter bei dem es klappt nicht sonderlich gut, deshalb würde ich gerne herausfinden wie ich es doch noch bei meinem Wunschanbieter hinbekomme.

Ich habe nun die Einstellungen der einen Datenbank bei der die Sonderzeichen korrekt ausgegeben werden versucht zu übernehmen, habe die alte Tabelle gelöscht, eine neue erstellt und von vornherein die Kollation auf utf8_general_ci und das Tabellenformat auf innoDB gesetzt.

Trotzdem werden immer noch Fragezeichen statt der Umlaute dargestellt............

2 1/2 Tage arbeite ich jetzt schon an dem Problem :( :( :(

Ich hoffe jemand hat noch eine Idee wie er mir helfen kann

--------EDIT------------
PS: Ich habe auch versucht die funktionierende Datenbank des neuen Anbieters zu importieren. Trotzdem werden die Umlaute als Fragezeichen dargestellt.

— geändert am 11.02.2014, 13:33:03

Antworten
Markus B.
  • Forum-Beiträge: 636

11.02.2014, 13:57:47 via Website

Hi,
das Problem was du hast ist ein klassisches encoding Problem. Mit diesem hat man in der Informatik immer wieder mal zu kämpfen.
Das liegt einfach daran das in deinem Fall schon mehrere Systeme involviert sind.

1. Deine Maschine(n) zum Entwickeln.
2. Dein Datenbanksystem.
3. Die Android-Geräte.

Jedes System kann hier ein anderes encoding fahren und deshalb geht es bei dir schief.
Das Problem lässt sich lösen in dem du Schritt für Schritt nachvollziehst wo du welches encoding benutzt. Wenn du dir an einer Stelle nicht
100%tig sicher bis, musst du halt LESEN und schauen was Sache ist.

Es gibt somit folgende Schritte ( als Anhaltspunkte zu verstehen ) zu prüfen:

1. Wie importierst du die Daten in die DB ?
- Welches encoding nutzt dann das Tool mit dem du arbeitest ?
- File Import: Welches encoding hat das System auf, welchem die Datei geschrieben wurde oder allgemein wie ist das File encodiert ?
- HTTP Post: Wie sieht es dort mit dem encoding aus?
2. Datenbank:
- Wie ist das default encoding ?
- Wie ist das Tabellen encoding ? Weicht es vom default encoding ab ?
3. Android:
- Wenn du hier das encoding richtig angibst ( zum Einlesen ) ist danach alles UTF-16. Ist halt Java.
- HTTP Post: Schickst du Daten per Http ? Dann sind die wenn du nichts machst auch UTF-16 codiert.

Wie du siehst kommt da einiges zusammen. Das macht es auch schwer dir zu helfen, da man sich eigentlich alles selber Schritt für Schritt anschauen müssen.
Dann in Ruhe NACHDENKEN was passiert und irgendwann kommt man auf die Lösung.

Motivation:
2 1/2 Tage an einem Problem hängen ist nicht viel ( Ich erinnere mich da gerne an segfaults die ich Wochen lang gesucht habe :) ). Gerade wenn man das erste Mal auf ein encoding-Problem trifft dauert das einfach. Nimm dir die Zeit und steck den Kopf nicht in den Sand. Einmal so was debuggen und beim Nächsten mal weißt du ganz schnell wo der Fehler liegt.

Gruß,
Markus

Ps.: Wenn du Problem einmal verstanden hast kannst du auch den encoding quatsch in dem php-Skript weglassen :)

— geändert am 11.02.2014, 13:59:30

Antworten
Alexej D.
  • Forum-Beiträge: 10

11.02.2014, 22:08:39 via Website

Hallo Markus vielen Dank für deine Hilfe und die tröstenden Worte ;-)

Ich habe jetzt mal alles versucht zu überprüfen:

1. Wie importierst du die Daten in die DB ?
zuerst per Hand aber ich habe auch versucht einen funktionierenden Datensatz zu importieren (die funktionierende DB nutzt allerdings utf8mb4, das kann ich bei mir jedoch nicht auswählen)
bei der Importierung: Zeichencodierung der Datei: utf8
- Welches encoding nutzt dann das Tool mit dem du arbeitest ?
Ich arbeite mit phpMyAdmin und laut Einstellungen utf8

- File Import: Welches encoding hat das System auf, welchem die Datei geschrieben wurde oder allgemein wie ist das File encodiert ?
von der langsameren Datenbank die funktioniert:
Server Zeichensatz: UTF-8 Unicode (utf8)
Zeichensatz/Kollation der MySQL-Verbindung :utf8mb4_general_ci
Datenbank die noch nicht funktioniert bzw bei der ich auf meiner Entwicklungsumgebung nur statt Umlauten Fragezeichen sehe:
Server Zeichensatz: UTF-8 Unicode (utf8)
Zeichensatz/Kollation der MySQL-Verbindung: utf_general_ci

- HTTP Post: Wie sieht es dort mit dem encoding aus?
Ich nutze die GET Methode. Bei der PostMethode wurde mir bei meinem Code ein Fehler ausgeben, außerdem konnte ich so über den Browser direkt testen ob es funktioniert.
PHP-Skript wurde im UTF8 Format gespeichert.

Aber hier mein POST Code vllt funktioniert es ja damit wenn die Fehler entfernt wurden.
1protected static String postSpalteDBnachID (int ID, String spalte) { //POST METHODE für int und String
2 try{
3
4 String link="domain/loginpost.php";
5 String data = URLEncoder.encode("ID", "UTF-8")
6 + "=" + URLEncoder.encode(ID, "UTF-8");
7 data += "&" + URLEncoder.encode("spalte", "UTF-8")
8 + "=" + URLEncoder.encode(spalte, "UTF-8");
9 URL url = new URL(link);
10 URLConnection conn = url.openConnection();
11 conn.setDoOutput(true);
12 OutputStreamWriter wr = new OutputStreamWriter
13 (conn.getOutputStream());
14 wr.write( data );
15 wr.flush();
16 BufferedReader reader = new BufferedReader
17 (new InputStreamReader(conn.getInputStream()));
18 StringBuilder sb = new StringBuilder();
19 String line = null;
20 // Read Server Response
21 while((line = reader.readLine()) != null)
22 {
23 sb.append(line);
24 break;
25 }
26 return sb.toString();
27 }catch(Exception e){
28 return new String("Exception: " + e.getMessage());
29 }
30
31 }

2. Datenbank:
- Wie ist das default encoding ?
Server Zeichensatz: UTF-8 Unicode (utf8)
Zeichensatz/Kollation der MySQL-Verbindung: utf_general_ci
- Wie ist das Tabellen encoding ?
hier habe ich schon alles ausprobiert.
Kein Tabellen encoding genutzt. Das gleiche encoding wie default und auch ein von Default abweichendes Encoding.
Alles ohne Erfolg

3. Android:
- Wenn du hier das encoding richtig angibst ( zum Einlesen ) ist danach alles UTF-16. Ist halt Java.
Wie mache ich das?
Ich hätte gedacht hier ist alles richtig weil es läuft ja über den langsameren Anbieter.

- HTTP Post: Schickst du Daten per Http ? Dann sind die wenn du nichts machst auch UTF-16 codiert.

Ich habe meine PHP-Funktion wie am Anfang des Postthreads angegeben bisher nicht verändert. Oder meinst du mit HTTP Post noch etwas anderes?

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

12.02.2014, 00:20:24 via App

Ich weiss nicht ob das jetzt stimmt,aber ist es nicht besser wenn man einem Http Post mit einem Apach HttpClient macht?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Markus B.
  • Forum-Beiträge: 636

12.02.2014, 07:57:11 via Website

Pascal P.
Ich weiss nicht ob das jetzt stimmt,aber ist es nicht besser wenn man einem Http Post mit einem Apache HttpClient macht?

Hallo,
nein das ist es nicht. Der HttpClient wird von google nicht mehr so wirklich supported siehe z.B. hier:
http://developer.android.com/reference/org/apache/http/impl/client/DefaultHttpClient.html
Quote: "Prefer HttpURLConnection for new code"
Es gibt zwar die Möglichkeit eine aktuelle Version der HttpClient mit Projekten wie diesem zu bekommen:
https://code.google.com/p/httpclientandroidlib/
Davon halte ich persönlich aber nicht viel. Ich nutzte http://square.github.io/okhttp/, welches auf HttpURLConnection aufsetzt.
Ein Post-Request ist für das übergeben von Parametern auch nicht nötig und somit kann er da ruhig GET fahren. POST nutzt du in er Regel, wenn die payload im body hast und diesen in irgendeiner Form in der DB auf dem Server speichern willst. Dazu empfehle ich mal eine Suche bei Tante google "restful services" und ein paar Stunden Zeit :)

@Alexej
Ich sehe da so einige Stellen bei denen es harkt. Ich brauche etwas Zeit um dir da eine passende Antwort zu bauen und bin mir nicht sicher, ob ich da vor Freitag noch zu komme.

Antworten