2012-05-14 11 views
7

Ich verwende Hibernate/Java, um eine Entität in einer Datenbank zu persistieren. Die Entität hat ein Passwort Feld, das ein String ist. Wenn ich einen Benutzer in meiner Anwendung registriere, hasse ich das Passwort mit SHA-1 (ich bestätige, dass es ein wenig schwach ist). Dies erzeugt ein byte [] die ich dann zu String konvertieren mit new String(byte[] arr); Immer, wenn ich möchte ein Benutzer anmelden, habe ich einfach den Hash-Passwort aus der Datenbank abrufen (wie String) und vergleichen Sie es mit dem Digest des Eingangs Passwort bei der Anmeldung hashedPasswordFromDatabase.equals(SHA1_HASH(inputPassword));Wie man eine byte [] Eigenschaft mit Hibernate?

das funktionierte perfekt auf meinem Entwicklungssystem (Windows 7, JDK 1.6.0_23/JDK 1.7, MySQL 5.5, Tomcat 6.0.26) verwenden, aber auf sie auf unserem Server bereitstellen (JDK 1.6 unter Linux laufen), die entspricht Methode nev Er berechnet TRUE auch für gleiche Passwörter. Ich habe schnell ein neues Entwicklungssystem (Ubuntu 12.04, MySQL 5.5, JDK 1.7.0_03, Tomcat 7.0.22) eingerichtet und es funktioniert auch nicht dort.

Ich bin mir der möglichen Codierungsprobleme bewusst, die in der Java-API-Dokumentation für die -Klasse angegeben sind und auch an einigen Stellen hier auf SO angegeben sind. Ich habe ein paar Codierungen in diesem Forum (z. B. Base64, Latin-1) vorgeschlagen und ich endete mit UnsupportedEncodingException. Ich denke, ich werde besser die String-Konvertierung vermeiden. Wie kann ich meine Datenbank so gestalten, dass die von Hibernate generierte Entitätsklasse byte [] für das Feld anstelle von String anzeigt?

+1

+1, sehr gute Frage. Nebenbei, das ist keine Antwort auf Ihre Frage, ich hatte sehr viel Glück mit einigen der Commons Base64-Dienstprogramme in und aus der Datenbank gehen. –

+2

Warum speichern Sie eine Zeichenfolge, die eine Zahl darstellt, anstatt die Nummer selbst zu speichern? – m0skit0

+0

Verwenden Sie keine Runde Hashing, um Passwörter zu schützen. Verwenden Sie etwas wie PBKDF2 oder bcrypt mit zehntausenden von Runden - sogar 100k ist nicht unvernünftig. Das direkte Speichern eines 'byte []' mit fester Länge sollte für mehrere Datenbanken einfach sein, aber Sie können immer einen 'BigInteger' aus einem Byte-Array erstellen und diesen als numerischen Typ speichern. – erickson

Antwort

5

Ja, das Problem ist höchstwahrscheinlich in byte[] zu String Umwandlung. Sie müssen wissen, dass SHA erzeugt byte Array und es gibt keine Garantie, dass willkürlich byte[] wird gültig String, unabhängig von der Codierung. Also Ihr Code funktionierte nur zufällig .

Vermeiden Sie das Problem ganz von:

  • roh byte[] in BLOB speichern - die sicherste und Lagerung effektive Weise. In Hibernate verwenden Sie einfach byte[] Eigenschaft auf Ihrem POJO.

  • encodieren byte[] mit (check out Decode Base64 data in Java) und speichern Sie es als eine Zeichenfolge.

BTW remember about salting!

+0

Vielen Dank. Meinst du, BLOB wird Hibernate dazu bringen, das Feld in der Entity als 'byte []' zu erzeugen? –

+0

@ SayoStealth-virusOladeji: Wenn Sie 'byte []' verwenden, sollte hbm2ddl BLOB generieren. Und umgekehrt - wenn Sie ein BLOB in Ihrer Datenbank haben, können Sie es sicher auf Byte [] 'abbilden. –

+0

Großartig! Ich gehe gerade die Base64-Seite durch, die Sie geteilt haben. es ist lesenswert. –

0

Sie können Ihre Byte an eine hexadezimale Darstellung wie folgt konvertieren:

public String encryptPassword(String passwordInClear) { 
      // Salt all you want here. 
      MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); 
    byte[] digest = sha256.digest(passwordInClear.getBytes()); 
    return digestToString(digest); 
} 

private String digestToString(byte[] digest) { 
    StringBuilder hashString = new StringBuilder(); 
    for (int i = 0; i < digest.length; i++) { 
     String hex = Integer.toHexString(digest[i]); 
     if (hex.length() == 1) { 
      hashString.append('0'); 
      hashString.append(hex.charAt(hex.length() - 1)); 
     } else { 
      hashString.append(hex.substring(hex.length() - 2)); 
     } 
    } 
    return hashString.toString(); 
} 
+0

Wie wirkt sich dies auf die Stärke des Hash-Passworts aus? Wird dieser Ansatz geschwächt? –

+0

@ SayoStealth-virusOladeji Nein, es schwächt es nicht oder stärkt es. Dies ist eine einfache Sache, die ein Byte auf seinen "äquivalenten" Zeichenfolgenwert abbildet, indem jedes Byte durch seinen numerischen Wert dargestellt wird (0 wird zu "00", 16 wird zu "10", 255 wird zu "FF" usw.). Der Übergang von einem zum anderen ist bidirektional, aber die wahre "Stärke" oder "Schwäche" liegt in der Verdichtung des Passworts. –

+0

Großartig! Danke vielmals. Ich denke, ich werde diesen Ansatz anwenden, da ich die Datenbank und andere Dinge, die damit in Verbindung stehen, nicht anfassen muss :) –

1

In meinem Fall die schlechte Datenbankdesign mich drücken, um einen Blob bei Clob zu verwenden. Die Lösung war Map in Hibernate die Eigenschaft mit der Lob Annotation und eine andere Eigenschaft in String-Typ.

In anderen Ebene des Codes, wenn ich die Get oder Set aufrufen, verwende ich die String-Eigenschaft und diese, erhalten oder setzen Sie den Byte-Array-Wert.

@Entity 
@Table(name = "CMUN_TAGS") 
@SequenceGenerator(name = "idSeqTag", sequenceName = "SEQ_CMUN_TAGS") 
public class CmunTagsDO implements java.io.Serializable { 
    private BigDecimal lngIdTag; 
    private byte[] blobValTag; 
    private String strValTag; 

    @Id 
    @Column(name = "LNG_ID_TAG", unique = true, nullable = false, precision = 20, scale = 0) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idSeqTag") 
    public BigDecimal getLngIdTag() { 
    return this.lngIdTag; 
    } 

    public void setLngIdTag(BigDecimal lngIdTag) { 
    this.lngIdTag = lngIdTag; 
    } 

    @Column(name = "BLOB_VAL_TAG", nullable = false) 
    @Lob 
    public byte[] getBlobValTag() { 
    return this.blobValTag; 
    } 

    public void setBlobValTag(byte[] blobValTag) { 
    this.blobValorTag = blobValorTag; 
    } 

    @Transient 
    public String getStrValTag() { 
    strValTag = new String(getBlobValTag()); 
    return strValTag; 
    } 

    public void setStrValTag(String strValTag) { 
    setBlobValTag(strValTag.getBytes()); 
    this.strValTag = strValTag; 
    } 
} 
Verwandte Themen