在django1.6中,默認的加密方式是pbkdf_sha256,具體算法不表,一直以來用django的自帶用戶驗證都十分順手,今天有需求,需要修改默認加密方式為md5,具體方法為:
在settings.py中加入
- PASSWORD_HASHERS = (
- 'myproject.hashers.MyMD5PasswordHasher',
- 'django.contrib.auth.hashers.MD5PasswordHasher',
- 'django.contrib.auth.hashers.PBKDF2PasswordHasher',
- 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
- 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
- 'django.contrib.auth.hashers.BCryptPasswordHasher',
- 'django.contrib.auth.hashers.SHA1PasswordHasher',
- 'django.contrib.auth.hashers.CryptPasswordHasher',
- )
PASSWORD_HASHERS = ( 'myproject.hashers.MyMD5PasswordHasher', 'django.contrib.auth.hashers.MD5PasswordHasher', 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', 'django.contrib.auth.hashers.BCryptPasswordHasher', 'django.contrib.auth.hashers.SHA1PasswordHasher', 'django.contrib.auth.hashers.CryptPasswordHasher', )
django會默認使用第一條加密方式。
這個是我自定義的加密方式,就是基本的md5,而django的MD5PasswordHasher是加鹽的。
以下是我的自定義hashers.py:
- from django.contrib.auth.hashers import BasePasswordHasher,MD5PasswordHasher
- from django.contrib.auth.hashers import mask_hash
- import hashlib
- class MyMD5PasswordHasher(MD5PasswordHasher):
- algorithm = "mymd5"
- def encode(self, password, salt):
- assert password is not None
- hash = hashlib.md5(password).hexdigest().upper()
- return hash
- def verify(self, password, encoded):
- encoded_2 = self.encode(password, '')
- return encoded.upper() == encoded_2.upper()
- def safe_summary(self, encoded):
- return OrderedDict([
- (_('algorithm'), algorithm),
- (_('salt'), ''),
- (_('hash'), mask_hash(hash)),
- ])
from django.contrib.auth.hashers import BasePasswordHasher,MD5PasswordHasher from django.contrib.auth.hashers import mask_hash import hashlib class MyMD5PasswordHasher(MD5PasswordHasher): algorithm = "mymd5" def encode(self, password, salt): assert password is not None hash = hashlib.md5(password).hexdigest().upper() return hash def verify(self, password, encoded): encoded_2 = self.encode(password, '') return encoded.upper() == encoded_2.upper() def safe_summary(self, encoded): return OrderedDict([ (_('algorithm'), algorithm), (_('salt'), ''), (_('hash'), mask_hash(hash)), ])之后可以在數據庫中看到,密碼確實使用了自定義的加密方式。
然而僅僅修改這些,在配合django的authenticate驗證時無法進行。
經過一些查找,發現需要在自定義authenticate。以下為方法:
在settings.py中加入以下:
- AUTHENTICATION_BACKENDS = (
- 'chicken.mybackend.MyBackend',
- )
AUTHENTICATION_BACKENDS = ( 'chicken.mybackend.MyBackend', )以下代碼為自定義的mybackend.py
- import hashlib
- from pro import models
- class MyBackend(object):
- def authenticate(self, username=None, password=None):
- try:
- user = models.M_User.objects.get(username=username)
- print user
- except Exception:
- print 'no user'
- return None
- if hashlib.md5(password).hexdigest().upper() == user.password:
- return user
- return None
- def get_user(self, user_id):
- try:
- return models.M_User.objects.get(id=user_id)
- except Exception:
- return None
import hashlib from pro import models class MyBackend(object): def authenticate(self, username=None, password=None): try: user = models.M_User.objects.get(username=username) print user except Exception: print 'no user' return None if hashlib.md5(password).hexdigest().upper() == user.password: return user return None def get_user(self, user_id): try: return models.M_User.objects.get(id=user_id) except Exception: return None
之后驗證成功。
當然經過這些修改后最終的安全性比起django自帶的降低很多,但是需求就是這樣的,必須滿足。
完成需求的過程中查找了不少資料,最后還是在django文檔中找到的答案,文檔還是很全全面的,以后通讀還是感覺有必要的。
考慮到Django有用戶驗證模塊,證明它已具備跨平台的加密模塊。
首先,引入模塊:
代碼如下 | 復制代碼 |
>>> from django.contrib.auth.hashers import make_password, check_password 生成密碼: |
這樣就可以利用django自帶的模塊生成一組密碼了,這個函數還有一個特點在於每次生成的密碼還不一樣:
代碼如下 | 復制代碼 |
|
既然每次生成的密文都不一樣,如何驗證用戶提交過來的明文與密文匹配呢?這就靠check_password去做了,check_password使用非常簡單,只需要告訴它明文和密文它就會返回False or True驗證結果
代碼如下 | 復制代碼 |
|
如果你不想每次都生成不同的密文,可以把make_password的第二個函數給一個固定的字符串,比如:
代碼如下 | 復制代碼 |
>>> make_password(text, "a", 'pbkdf2_sha256') u'pbkdf2_sha256$12000$a$5HkIPczRZGSTKUBa5uzZmRuAWdp2Qe6Oemhdasvzv4Q=' >>> make_password(text, "a", 'pbkdf2_sha256') u'pbkdf2_sha256$12000$a$5HkIPczRZGSTKUBa5uzZmRuAWdp2Qe6Oemhdasvzv4Q=' |
只要是任意字符串就可以,並且可以多個。但不能為空,如:
代碼如下 | 復制代碼 |
|
為空的字符串就相當於:
1
代碼如下 | 復制代碼 |
make_password(text, None, 'pbkdf2_sha256') |
至於make_password第三個參數是表示生成密文的一種方式,根據文檔給出的大概有這幾種:
代碼如下 | 復制代碼 |
pbkdf2_sha256 |
以上例子我使用了第一種加密方式pbkdf2_sha256,crypt和bcrypt都需要另外單獨安裝模塊,unsalted_md5就是常見的md5加密,如果對加密哈希算法不是很了解,那么就使用django最新的哈希算法pbkdf2_sha256就好