Django 自帶密碼加密,自定密碼加密方式 及自定義驗證方式


 

在django1.6中,默認的加密方式是pbkdf_sha256,具體算法不表,一直以來用django的自帶用戶驗證都十分順手,今天有需求,需要修改默認加密方式為md5,具體方法為:

在settings.py中加入

[python] view plain copy
print ?
  1. PASSWORD_HASHERS = (  
  2.   
  3.     'myproject.hashers.MyMD5PasswordHasher',  
  4.     'django.contrib.auth.hashers.MD5PasswordHasher',  
  5.     'django.contrib.auth.hashers.PBKDF2PasswordHasher',  
  6.     'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',  
  7.     'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',  
  8.     'django.contrib.auth.hashers.BCryptPasswordHasher',  
  9.     'django.contrib.auth.hashers.SHA1PasswordHasher',  
  10.     'django.contrib.auth.hashers.CryptPasswordHasher',  
  11. )  
 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:

 

[python] view plain copy
print ?
  1. from django.contrib.auth.hashers import BasePasswordHasher,MD5PasswordHasher  
  2. from django.contrib.auth.hashers import mask_hash  
  3. import hashlib  
  4.   
  5. class MyMD5PasswordHasher(MD5PasswordHasher):  
  6.     algorithm = "mymd5"  
  7.   
  8.     def encode(self, password, salt):  
  9.         assert password is not None  
  10.         hash = hashlib.md5(password).hexdigest().upper()  
  11.         return hash  
  12.   
  13.     def verify(self, password, encoded):  
  14.         encoded_2 = self.encode(password, '')  
  15.         return encoded.upper() == encoded_2.upper()  
  16.   
  17.     def safe_summary(self, encoded):  
  18.         return OrderedDict([  
  19.                 (_('algorithm'), algorithm),  
  20.                 (_('salt'), ''),  
  21.                 (_('hash'), mask_hash(hash)),  
  22.                 ])  
  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中加入以下:

 

[python] view plain copy
print ?
  1. AUTHENTICATION_BACKENDS = (  
  2.     'chicken.mybackend.MyBackend',  
  3. )  
AUTHENTICATION_BACKENDS = (
    'chicken.mybackend.MyBackend',
)
以下代碼為自定義的mybackend.py

 

 

[python] view plain copy
print ?
  1. import hashlib  
  2. from pro import models  
  3.   
  4. class MyBackend(object):  
  5.     def authenticate(self, username=None, password=None):  
  6.         try:  
  7.             user = models.M_User.objects.get(username=username)  
  8.             print user  
  9.         except Exception:  
  10.             print 'no user'  
  11.             return None  
  12.         if hashlib.md5(password).hexdigest().upper() == user.password:  
  13.             return user  
  14.         return None  
  15.   
  16.     def get_user(self, user_id):  
  17.         try:  
  18.             return models.M_User.objects.get(id=user_id)  
  19.         except Exception:  
  20.             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

生成密碼:
 
>>> make_password("www.111cn.net", None, 'pbkdf2_sha256')
u'pbkdf2_sha256$12000$H6HRZD4DDiKg$RXBGBTiFWADyw+J9O7114vxKvysBVP+lz7oSYxkoic0='

這樣就可以利用django自帶的模塊生成一組密碼了,這個函數還有一個特點在於每次生成的密碼還不一樣:

 代碼如下 復制代碼

 
>>> make_password("www.111cn.net", None, 'pbkdf2_sha256')
u'pbkdf2_sha256$12000$H6HRZD4DDiKg$RXBGBTiFWADyw+J9O7114vxKvysBVP+lz7oSYxkoic0='
 
>>> make_password("www.111cn.net", None, 'pbkdf2_sha256')
u'pbkdf2_sha256$12000$9l09rJd9MbQj$0tJVXBZFN6WwD/qI3WELdrRWOU7Inb7im3uB/np2PPg='
 
>>> make_password("www.111cn.net", None, 'pbkdf2_sha256') == make_password("www.111cn.net", None,
'pbkdf2_sha256')
False

既然每次生成的密文都不一樣,如何驗證用戶提交過來的明文與密文匹配呢?這就靠check_password去做了,check_password使用非常簡單,只需要告訴它明文和密文它就會返回False or True驗證結果

 代碼如下 復制代碼

 
>>> text = "www.111cn.net"
>>> passwd = make_password(text, None, 'pbkdf2_sha256')
>>> print passwd 
pbkdf2_sha256$12000$xzMLhCNvQbb8$i1XDnJIpb/cRRGRX2x7Ym74RNfPRCUp5pbU6Sn+V3J0=
>>> print check_password(text, passwd)
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='

只要是任意字符串就可以,並且可以多個。但不能為空,如:

 代碼如下 復制代碼

 
>>> make_password(text, "", 'pbkdf2_sha256')
u'pbkdf2_sha256$12000$KBcG81bWMAvd$aJNgfTOGFhOGogLSTE2goEM3ifKZZ1hydsuFEqnzHXU='
 
>>> make_password(text, "", 'pbkdf2_sha256')
u'pbkdf2_sha256$12000$fNv3YU4kgyLR$1FI8mxArDHt6Hj/eR72YCylGTAkW7YMWTj+wV4VHygY='

為空的字符串就相當於:
1

 代碼如下 復制代碼
 
make_password(text, None, 'pbkdf2_sha256')

至於make_password第三個參數是表示生成密文的一種方式,根據文檔給出的大概有這幾種:

 代碼如下 復制代碼

    pbkdf2_sha256
    pbkdf2_sha1
    bcrypt_sha256
    bcrypt
    sha1
    unsalted_md5
    crypt

以上例子我使用了第一種加密方式pbkdf2_sha256,crypt和bcrypt都需要另外單獨安裝模塊,unsalted_md5就是常見的md5加密,如果對加密哈希算法不是很了解,那么就使用django最新的哈希算法pbkdf2_sha256就好



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM