2012-03-26 31 views
10

Tôi đang di chuyển một trang web từ Drupal 7 sang Django 1.4, bao gồm cả người dùng hiện tại. Làm thế nào tôi có thể làm việc với các mật khẩu đã được băm bởi Drupal?Di chuyển mật khẩu từ Drupal 7 sang Django

Theo this, Drupal 7 băm mật khẩu bằng SHA-512 (chúng được lưu trữ dưới dạng chuỗi bắt đầu bằng "$ S $").

Django 1.4 hiện chứa một số options để lưu trữ mật khẩu, với mặc định là SHA-256, nhưng tôi không thể tìm thấy tùy chọn cho SHA-512. Trong khi this app xuất hiện để cho phép sử dụng thuật toán SHA2, tôi không chắc chắn nó tương thích với Django 1.4 (như 1.4 có một mật khẩu linh hoạt hasher).

Cách đơn giản nhất để thực hiện việc này là gì?

ETA: Tôi đã xây dựng một hasher mật khẩu bắt chước thuật toán của Drupal và giúp việc di chuyển trở nên dễ dàng. Kể từ khi tôi đã chấp nhận một câu trả lời, tôi sẽ không chấp nhận, nhưng đối với bất cứ ai muốn làm Drupal để Django di cư trong tương lai, mã được lưu trữ trên Django snippets và như là một GitHub gist.

+0

Tôi đang cố di chuyển người dùng từ ứng dụng Drupal 7 sang ứng dụng Django 1.8 có sử dụng Stormpath. (Theo http://drupal.stackexchange.com/questions/176008/getting-password-hashes-and-salts-from-drupal-7). Những gì tôi đang mắc kẹt là làm thế nào để có được băm mật khẩu và muối ra khỏi ứng dụng Drupal. Bạn có thể vui lòng giúp với điều đó? – Daniel

Trả lời

5

Tôi không biết Drupal rất tốt, nhưng tôi cho rằng mật khẩu được lưu trữ băm. Nếu đó là trường hợp, bạn sẽ phải sao chép các mật khẩu (tôi có nghĩa là, sao chép chúng không thay đổi) và bạn sẽ phải thay đổi cách Django băm mật khẩu của nó, bằng cách sử dụng chính xác cùng một cách của Drupal, với cùng một muối an ninh.

Tôi thực sự không biết cách thực hiện điều đó, nhưng logic cho mật khẩu được chứa trong đối tượng Người dùng. Ví dụ. chức năng User.set_password() (được mô tả here) sử dụng chức năng make_password.

Tôi nghĩ rằng với một ít nghiên cứu bạn sẽ tìm thấy cách để thay đổi nó, nhưng điều quan trọng là, hãy nhớ rằng các chức năng phải bằng! tức là:

drupal_hash (x) == django_hash (x) cho mỗi x trong mật khẩu được phép đặt.

EDIT:

Lấy một cái nhìn sâu sắc hơn django có được có chức năng với get_hasher chức năng. Bây giờ trong phiên bản 1.4 có một cách để xác định cách Django sẽ chọn chức năng đó. Hãy xem điều này: https://docs.djangoproject.com/en/dev/topics/auth/#how-django-stores-passwords

Cuối cùng, để tạo chức năng của riêng bạn, bạn có thể xem cách thực hiện nó trên MD5PasswordHasher. Nó có vẻ rất đơn giản. Bạn có thể sử dụng hashlib python library để tạo thuật toán sha-512.

Thay đổi phương pháp mã hóa sẽ đòi hỏi somthing tương tự như:

def encode(self, password, salt): 
    assert password 
    assert salt and '$' not in salt 
    hash = hashlib.sha512(salt + password).hexdigest() 
    return "%s$%s$%s" % (self.algorithm, salt, hash) 
+0

Đó chính xác là vấn đề tôi gặp phải: Tôi chưa tìm thấy cách nào để sử dụng băm SHA-512 ở Django, dường như là phương pháp băm của Drupal 7 –

+0

Tôi đã cập nhật câu trả lời của mình, hy vọng nó sẽ giúp ích. – santiagobasulto

+0

Nó! Nhưng như @Alasdiar nói, tôi không chắc chắn làm thế nào để trích xuất muối từ mật khẩu được lưu trữ ... –

1

Bạn sẽ có thể thực hiện điều này bằng cách tạo lớp con của riêng bạn BasePasswordHasher, và thêm nó vào khung cảnh PASSWORD_HASHERS của bạn.

Thực hiện hashlib của Python sha512.

page David linked to in the question giải thích cách số lần lặp (16385 cho Drupal 7) được mã hóa trong mã băm, nhưng không rõ với tôi cách lấy muối.

Chỉnh sửa: Trong nhận xét cho câu trả lời của @ santiago, David nói "muối là ký tự thứ 5 đến ngày thứ 12 trong chuỗi Drupal được lưu trữ".

+1

muối trong drupal được lưu trữ trong tập tin settings.php. – mirzu

+1

Giải quyết mã này được đăng trong câu hỏi của tôi ở trên :-) –

+0

Đẹp một David. Cảm ơn đã đưa ra giải pháp của bạn. – Alasdair

2

Cảm ơn bạn, David Robinson, về mã của bạn. Điều đó làm cho ngày của tôi! Dường như có một lỗ hổng, mặc dù: Nếu Drupal quyết định không sử dụng 'C' nhưng 'D' cho số lần lặp lại, nó không thành công. Tôi đã sửa định nghĩa lớp học một chút:

class DrupalPasswordHasher(BasePasswordHasher): 
    algorithm = "S" 
    iter_code = 'C' 
    salt_length = 8 

    def encode(self, password, salt, iter_code=None): 
     """The Drupal 7 method of encoding passwords""" 
     if iter_code == None: 
      iterations = 2 ** _ITOA64.index(self.iter_code) 
     else: 
      iterations = 2 ** _ITOA64.index(iter_code) 
     hash = hashlib.sha512(salt + password).digest() 

     for i in range(iterations): 
      hash = hashlib.sha512(hash + password).digest() 

     l = len(hash) 

     output = '' 
     i = 0 

     while i < l: 
      value = ord(hash[i]) 
      i = i + 1 

      output += _ITOA64[value & 0x3f] 
      if i < l: 
       value |= ord(hash[i]) << 8 

      output += _ITOA64[(value >> 6) & 0x3f] 
      if i >= l: 
       break 
      i += 1 

      if i < l: 
       value |= ord(hash[i]) << 16 

      output += _ITOA64[(value >> 12) & 0x3f] 
      if i >= l: 
       break 
      i += 1 

      output += _ITOA64[(value >> 18) & 0x3f] 

     longhashed = "%s$%s%s%s" % (self.algorithm, iter_code, 
            salt, output) 
     return longhashed[:54] 

    def verify(self, password, encoded): 
     hash = encoded.split("$")[1] 
     iter_code = hash[0] 
     salt = hash[1:1 + self.salt_length] 
     return encoded == self.encode(password, salt, iter_code) 
+0

Vui vì điều này có thể giúp, Karsten! Tôi nghĩ rằng tôi đang bối rối về cách mã của bạn khác nhau: không phải là điều này được xử lý bởi dòng ban đầu 'iterations = 2 ** _ITOA64.index (hash [0])'? BTW, tôi đang duy trì mã như một GitHub gist, xem câu trả lời để biết chi tiết. (Tôi đã chỉnh sửa nó cho phiên bản của bạn bây giờ). –

+0

(Để so sánh, [ở đây] (https://gist.github.com/2344345/2f9f79fccef285ff4282ac640cf8cfb56fb069fd) là mã gốc) –

+0

Xem lại điều này, tôi có xu hướng đồng ý. Có thể nó chỉ là một vấn đề dễ đọc khiến tôi bối rối, với 'iterations' là 'C' và' 2 ** _ITOA64.index ('C') 'cùng một lúc, và sau đó tôi giải quyết bằng cách tạo' iter_code' hiệu quả một nhân vật chính, và 'iterations' sức mạnh của hai số nguyên. Bây giờ tôi thấy rằng tôi có thể đạt được điều đó với ít dòng mã thay đổi hơn. Dù sao, đoạn mã tuyệt vời, cảm ơn sự giúp đỡ của bạn! –

0

Đây là bản cập nhật cho câu trả lời tuyệt vời của David cho python 3, vì hashlib không còn chấp nhận chuỗi nữa. Ngoài ra, điều này bao gồm hỗ trợ cho băm "U $ S $ *" lẻ, mà rõ ràng là từ một bản cập nhật và tôi tìm thấy một bó của chúng trong cơ sở dữ liệu drupal của tôi.

https://gist.github.com/skulegirl/bec420b5272b87d9e4dbd39e947062fc

Và như một phần thưởng, đây là đoạn code mà tôi sử dụng để import file xml của tôi về dữ liệu người dùng nhập. (Tôi chỉ cần tạo file xml qua xuất khẩu sql sau khi thực hiện một truy vấn trên bảng người sử dụng.)

import xml.etree.ElementTree as ET 
from django.contrib.auth.models import User 

tree = ET.parse('/PATH/TO/Users.xml') 
root = tree.getroot() 

for row in root: 
    user_dict = {} 
    for field in row: 
     user_dict[field.attrib['name']] = field.text 
    user = User.objects.create_user(user_dict['name'], user_dict['mail']) 
    if user_dict['pass'][0] == '$': 
     user_dict['pass'] = user_dict['pass'][1:] 
    user.password = user_dict['pass'] 
    user.save() 
Các vấn đề liên quan