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

在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 生成密码:   >>> 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就好

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT杂记

Mapreduce 任务提交源码分析1

提交过程 一般我们mapreduce任务是通过如下命令进行提交的 $HADOOP_HOME/bin/hadoop jar $MR_JAR $MAIN_CLASS...

2506
来自专栏地方网络工作室的专栏

Shell 命令行,实现一个获取任意位数的随机密码的脚本

Shell 命令行,实现一个获取任意位数的随机密码的脚本 每次我们想要获得一个密码的时候都很头疼,于是我之前自己用nodejs写了一个 Shell 脚本。这两天...

2006
来自专栏安恒网络空间安全讲武堂

[安全入门教学]如何分析海洋CMS漏洞

看到freebuf上有一篇为《漏洞预警 | 海洋CMS(SEACMS)0day漏洞预警》的文章,展示了关于漏洞使用的POC,这里我们来完整的分析一下POC的原理...

2K10
来自专栏行者常至

(17)Struts2_异常处理: exception-mapping 元素

1052
来自专栏LanceToBigData

struts2(三)之表单参数自动封装与参数类型自动转换

前言   对struts2的使用不外乎这几点,参数自动封装,拦截器的使用,数据校验,ognl表达(值栈和actionContext的讲解),struts2的标签...

24310
来自专栏小勇DW3

自己手动写代码实现数据库连接池

池:一个高级的集合体(集合存储元素 + 管理方式–>提高效率),是对外提供同一种类型对象的集合,如(线程池、数据库连接池)  特性:复用性(每条连接可重复使用)...

1503
来自专栏牛肉圆粉不加葱

Spark Sql 源码剖析(三):Analyzer

当一条 sql 语句被 SparkSqlParser 解析为一个 unresolved logicalPlan 后,接下来就会使用 Analyzer 进行 re...

1222
来自专栏python3

习题17:更多文件操作

import了又一个很好用的命令exists,这个命令将文件名字符串作为参数,如果文件存在的话,它将返回True,否则将返回False

671
来自专栏Java 技术分享

Struts2 之值栈

2898
来自专栏枕边书

搭建自己的PHP框架心得(二)

续言 对于本次更新,我想说: 本框架由本人挑时间完善,而我还不是PHP大神级的人物,所以框架漏洞难免,求大神们指出。 本框架的知识点应用都会写在博客里,大家有什...

2418

扫码关注云+社区

领取腾讯云代金券