• Django 自带密码加密,自定密码加密方式 及自定义验证方式


     

    在django1.6中,默认的加密方式是pbkdf_sha256,具体算法不表,一直以来用django的自带用户验证都十分顺手,今天有需求,需要修改默认加密方式为md5,具体方法为:

    在settings.py中加入

    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:

    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中加入以下:

    1. AUTHENTICATION_BACKENDS = (  
    2.     'chicken.mybackend.MyBackend',  
    3. )  
    AUTHENTICATION_BACKENDS = (
        'chicken.mybackend.MyBackend',
    )
    
    以下代码为自定义的mybackend.py
    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就好


  • 相关阅读:
    编程思想-模块化-模块化程序设计:模块化程序设计
    编程思想-模块化-产品模块化设计:产品模块化设计
    编程思想-模块化-模块化设计:模块化设计
    编程思想-模块化:目录
    编程思想-模块化:模块化
    Java学习笔记----main
    jdbc连接hive0.14
    黑马day18 鼠标事件&图片变大
    HLJU 1046: 钓鱼(数据增强版) (贪心+优化)
    怎样打包下载源码
  • 原文地址:https://www.cnblogs.com/huchong/p/7867123.html
Copyright © 2020-2023  润新知