2012-05-14 39 views
7

Tôi đang sử dụng Hibernate/Java để duy trì một thực thể cho một cơ sở dữ liệu. Pháp nhân có một trường mật khẩuChuỗi. Khi đăng ký một người dùng trong ứng dụng của tôi, tôi băm mật khẩu bằng SHA-1 (tôi thừa nhận đây là một chút yếu). Điều này tạo ra một byte [] mà tôi sau đó chuyển sang Chuỗi sử dụng new String(byte[] arr); Bất cứ khi nào tôi muốn đăng nhập người dùng vào, tôi chỉ đơn giản lấy lại mật khẩu băm từ cơ sở dữ liệu (như Chuỗi) và so sánh nó với tiêu hóa của mật khẩu đầu vào lúc đăng nhập sử dụng hashedPasswordFromDatabase.equals(SHA1_HASH(inputPassword));Làm thế nào để ánh xạ một thuộc tính byte [] với Hibernate?

này đã làm việc một cách hoàn hảo trên hệ thống phát triển của tôi (Windows 7, JDK 1.6.0_23/JDK 1.7, MySQL 5.5, Tomcat 6.0.26) nhưng khi triển khai nó trên máy chủ của chúng tôi (chạy JDK 1.6 trên Linux), bằng phương pháp nev er đánh giá thành TRUE ngay cả đối với mật khẩu bằng nhau. Tôi nhanh chóng thiết lập một hệ thống phát triển mới (Ubuntu 12.04, MySQL 5.5, JDK 1.7.0_03, Tomcat 7.0.22) và nó cũng không hoạt động ở đó.

Tôi biết các vấn đề mã hóa có thể được nêu trong tài liệu Java API cho lớp Chuỗi và cũng được nêu ở một số nơi ở đây trên SO. Tôi đã thử một vài mã hóa được đề xuất trên diễn đàn này (ví dụ: Base64, Latin-1) và tôi đã kết thúc với UnsupportedEncodingException. Tôi nghĩ rằng tôi sẽ tốt hơn để tránh chuyển đổi Chuỗi. Vì vậy, làm cách nào để thiết kế cơ sở dữ liệu của tôi sao cho lớp tổ chức được tạo Hibernate đi kèm với byte [] cho trường hợp mật khẩu thay vì Chuỗi?

+1

+1, câu hỏi rất hay. Là một bên không phải là một câu trả lời cho câu hỏi của bạn, tôi đã có may mắn rất tốt bằng cách sử dụng một số tiện ích Commons Base64 đi vào và ra khỏi cơ sở dữ liệu. –

+2

Tại sao bạn lưu trữ một chuỗi đại diện cho một số thay vì lưu trữ chính số đó? – m0skit0

+0

Không sử dụng một vòng băm để bảo vệ mật khẩu. Sử dụng một cái gì đó như PBKDF2 hoặc bcrypt với 10s của hàng ngàn vòng --- thậm chí 100k không phải là không hợp lý. Việc lưu trữ một 'byte []' có độ dài cố định trực tiếp nên dễ dàng cho nhiều cơ sở dữ liệu hơn, nhưng bạn luôn có thể tạo một 'BigInteger' từ một mảng byte và lưu trữ nó như là một kiểu số. – erickson

Trả lời

5

Có, rất có thể sự cố trong chuyển đổi byte[] sang String. Bạn phải biết rằng SHA sản xuất mảng thô byte và không đảm bảo rằng tùy ý byte[] sẽ sản xuất hợp lệ String, không phân biệt mã hóa. Do đó, mã của bạn chỉ hoạt động do tai nạn.

Tránh những vấn đề hoàn toàn bằng cách:

  • lưu trữ thô byte[] trong BLOB - cách lưu trữ hiệu quả an toàn nhất và nhiều nhất. Trong Hibernate, bạn chỉ cần sử dụng thuộc tính byte[] trên POJO của mình.

  • mã hóa byte[] sử dụng (xem Decode Base64 data in Java) và lưu trữ dưới dạng chuỗi.

BTW remember about salting!

+0

Cảm ơn rất nhiều. Bạn có nghĩa là BLOB sẽ thực sự làm cho Hibernate tạo ra trường trong thực thể dưới dạng 'byte []'? –

+0

@ SayoStealth-virusOladeji: Nếu bạn sử dụng 'byte []', hbm2ddl sẽ tạo BLOB. Và ngược lại - nếu bạn có BLOB trong cơ sở dữ liệu của mình, bạn có thể ánh xạ nó một cách an toàn đến 'byte []'. –

+0

Tuyệt vời! Tôi hiện đang xem trang Base64 mà bạn chia sẻ; đáng đọc của nó. –

0

Bạn có thể chuyển đổi byte của bạn đến một đại diện thập lục phân như thế này:

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

Điều này ảnh hưởng như thế nào đến sức mạnh của mật khẩu băm? Cách tiếp cận này có làm suy yếu nó không? –

+0

@ SayoStealth-virusOladeji Không, nó không làm suy yếu hoặc tăng cường nó. Đây là một điều đơn giản để ánh xạ một byte vào giá trị chuỗi "tương đương" của nó bằng cách biểu diễn từng byte theo giá trị số của nó (0 trở thành "00", 16 trở thành "10", 255 trở thành "FF", v.v ...). Việc chuyển từ người này sang người khác là hai chiều nhưng "sức mạnh" hay "điểm yếu" thực sự là trong việc tiêu hóa mật khẩu của bạn. –

+0

Tuyệt vời! Cảm ơn rất nhiều. Tôi nghĩ rằng tôi sẽ sử dụng phương pháp này vì tôi sẽ không phải chạm vào cơ sở dữ liệu và bất kỳ thứ gì gần gũi với nó :) –

1

Trong trường hợp của tôi, thiết kế cơ sở dữ liệu xấu đẩy tôi sử dụng một Blob trong trường hợp CLOB. Giải pháp là Map in hibernate thuộc tính với chú thích Lob và đặt một thuộc tính khác trong kiểu String.

Ở cấp độ khác của mã, khi tôi gọi lệnh get hoặc set, tôi sử dụng thuộc tính String và thuộc tính này, nhận hoặc đặt giá trị mảng byte.

@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; 
    } 
} 
Các vấn đề liên quan