铁乐学python26_hashlib+configparser+logging模块

大部份内容摘自博客http://www.cnblogs.com/Eva-J/

hashlib模块算法介绍

Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。

什么是摘要算法呢?

摘要算法又称哈希算法、散列算法。

它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。

摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,

目的是为了发现原始数据是否被人篡改过。

摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,

计算f(data)很容易,但通过digest反推data却非常困难。

而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。

我们以常见的摘要算法MD5为例,

计算出一个字符串的MD5值:
import hashlib
md5 = hashlib.md5()
md5.update(b‘how to use md5 in python hashlib?‘) #注,要转换成b字节模式才能正常
print(md5.hexdigest()) # d26a53750bc40b38b65a520292f69306

如果数据量很大,可以分块多次调用update(),
一段字符串直接进行摘要和分成几段摘要的结果是相同的:

md5 = hashlib.md5()
md5.update(b‘how to use md5 in ‘)
md5.update(b‘python hashlib?‘)
print(md5.hexdigest()) # d26a53750bc40b38b65a520292f69306

模仿文件校验md5一致
def check_md5(filename):
    md5 = hashlib.md5()
    with open(filename, ‘rb‘) as f:
        while True:
            content = f.read(4096) # 分段读取,防止占用大段内存
            if content:
                md5.update(content)
            else:
                break
    return md5.hexdigest()

file1 = check_md5(‘md5-test1‘)
file2 = check_md5(‘md5-test2‘)
print(file1) # 2e5f9458bcd27e3c2b5908af0b91551a
print(file2) # 2e5f9458bcd27e3c2b5908af0b91551a

md5摘要加密传输进来的明文密码,且动态加盐(更安全)
import hashlib
# md5摘要加密传输进来的明文密码
def md5_digest(user, plain_pass):
    md5 = hashlib.md5(user[::-1].encode(‘utf-8‘)) # 创建了一个md5算法的对象,且对定义的盐切片倒序
    md5.update(plain_pass.encode(‘utf-8‘))
    return md5.hexdigest()

user = ‘bilibili‘
pwd = ‘123456‘
print(md5_digest(user, pwd))  # b442d27216d7e1dd54d6419a9d31056f

MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。

另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似,就是将前面的md5改成sha1而己。

SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。

比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。

摘要算法应用

任何允许用户登录的网站都会存储用户登录的用户名和口令。

如何存储用户名和口令呢?方法是存到数据库表中:

name    | password
--------+----------
michael | 123456
bob     | abc999
alice   | alice2008
如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。
此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。
正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:
username | password
---------+---------------------------------
michael  | e10adc3949ba59abbe56e057f20f883e
bob      | 878ef96e86145580c38c87f0410ad153
alice    | 99b1c2188db85afee403b1536010c2c9

考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令,
于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:
‘e10adc3949ba59abbe56e057f20f883e‘: ‘123456‘
‘21218cca77804d2ba1922c33e0151105‘: ‘888888‘
‘5f4dcc3b5aa765d61d8327deb882cf99‘: ‘password‘

这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。

对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?

由于常用口令的MD5值很容易被计算出来,

所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,

这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:

(有点像三国演义中杨修死于曹操随口感慨的‘鸡肋’一夜巡口令)

hashlib.md5("salt".encode("utf8"))

经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。

但是如果有两个用户都使用了相同的简单口令比如123456,

在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。

有没有办法让使用相同口令的用户存储不同的MD5呢?

如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,

从而实现相同口令的用户也存储不同的MD5。

摘要算法在很多地方都有广泛的应用。

要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,

但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。

configparser模块

开发流程:一般开发完成后先给予测试,测试通过后再给实施或运维部门部署到线上。

需要配置文件以便运维部门或开源项目的话给到用户自定义一些符合实际的参数,而不需要到代码文件里修改。

该模块适用于配置文件的格式与windows ini文件类似,

可以包含一个或多个节(section),每个节可以有多个option参数(键=值)。

创建配置文件

常见文档格式如下:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no

用python生成一个配置文件:
import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {‘ServerAliveInterval‘: ‘45‘,
                     ‘Compression‘: ‘yes‘,
                     ‘CompressionLevel‘: ‘9‘,
                     ‘ForwardX11‘:‘yes‘
                     }
config[‘bitbucket.org‘] = {‘User‘:‘hg‘}
config[‘topsecret.server.com‘] = {‘Host Port‘:‘50022‘,‘ForwardX11‘:‘no‘}
with open(‘example.ini‘, ‘w‘) as configfile:
config.write(configfile)

生成的example.ini如下,注意里面的选项会变成小写(不区分大小写):
[DEFAULT]
compressionlevel = 9
serveraliveinterval = 45
forwardx11 = yes
compression = yes

[bitbucket.org]
user = hg

[topsecret.server.com]
host port = 50022
forwardx11 = no

查看配置文件
由上至下依次敲入执行来看效果
import configparser
config = configparser.ConfigParser()
#---------------------------查找文件内容,基于字典的形式
print(config.sections())        #  显示[] ,默认,因这个时候还不知道要读取哪个配置文件的内容
config.read(‘example.ini‘)      #  读取前面创建好的那个配置文件示例内容
print(config.sections())        #  这回显示出[‘bitbucket.org‘, ‘topsecret.server.com‘]
print(‘bytebong.com‘ in config) #  判断有无此参数在配置文件中 False
print(‘bitbucket.org‘ in config) # 判断有无此参数在配置文件中 True
print(config[‘bitbucket.org‘]["user"])  # 类似字典通过key找值 hg
print(config[‘DEFAULT‘][‘Compression‘]) # yes
print(config[‘topsecret.server.com‘][‘ForwardX11‘])  # no
print(config[‘bitbucket.org‘])          # 查看对象 <Section: bitbucket.org>

for key in config[‘bitbucket.org‘]:     # 注意,有default会默认default的键
    print(key)
# user
# compressionlevel
# serveraliveinterval
# forwardx11
# compression

print(config.options(‘bitbucket.org‘))  # 同for循环,找到‘bitbucket.org‘下所有键
print(config.items(‘bitbucket.org‘))    # 找到‘bitbucket.org‘下所有键值对
# [(‘compressionlevel‘, ‘9‘), (‘serveraliveinterval‘, ‘45‘), (‘forwardx11‘, ‘yes‘), (‘compression‘, ‘yes‘), (‘user‘, ‘hg‘)]
print(config.get(‘bitbucket.org‘,‘compression‘)) # yes       get方法Section下的key对应的value

增删改配置文件:
import configparser
config = configparser.ConfigParser()
config.read(‘example.ini‘)
config.add_section(‘yuan‘)
# 注,此时还只是在内存中读取出配置文件内容,
# 并在内存中添加了,还需执行最下方的写入句柄操作才能生效,下面的操作同理
config.remove_section(‘bitbucket.org‘)
config.remove_option(‘topsecret.server.com‘, "forwardx11")
# remove 移除
config.set(‘topsecret.server.com‘, ‘k1‘, ‘11111‘)
config.set(‘yuan‘, ‘k2‘, ‘22222‘)
# set 增加或修改
config.write(open(‘example.ini‘, "w"))

执行完后,原配置文件被改成了如下模样:
[DEFAULT]
compressionlevel = 9
serveraliveinterval = 45
forwardx11 = yes
compression = yes

[topsecret.server.com]
host port = 50022
k1 = 11111

[yuan]
k2 = 22222

logging模块
函数式简单配置
import logging
logging.debug(‘debug message‘)
logging.info(‘info message‘)
logging.warning(‘warning message‘)
logging.error(‘error message‘)
logging.critical(‘critical message‘) 

默认情况下Python的logging模块将日志打印到了标准输出中,
且只显示了大于等于WARNING级别的日志,
这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),
默认的日志格式为日志级别:Logger名称:用户输出消息。

灵活配置日志级别,日志格式,输出位置:
import logging
logging.basicConfig(level=logging.DEBUG,
                    format=‘%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s‘,
                    datefmt=‘%a, %d %b %Y %H:%M:%S‘,
                    filename=‘test.log‘,
                    filemode=‘w‘)  

logging.debug(‘debug message‘)
logging.info(‘info message‘)
logging.warning(‘warning message‘)
logging.error(‘error message‘)
logging.critical(‘critical message‘)

查看test.log:
Mon, 23 Apr 2018 20:45:04 hashlib_test.py[line:205] DEBUG debug message
Mon, 23 Apr 2018 20:45:04 hashlib_test.py[line:206] INFO info message
Mon, 23 Apr 2018 20:45:04 hashlib_test.py[line:207] WARNING warning message
Mon, 23 Apr 2018 20:45:04 hashlib_test.py[line:208] ERROR error message
Mon, 23 Apr 2018 20:45:04 hashlib_test.py[line:209] CRITICAL critical message

logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:

filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”(追加模式)还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式,设置asctime中的时间显示格式。
level:设置rootlogger的日志级别,可选DEBUG调试/INFO正常/WARNING警告/ERROR错误/CRITICAL严重错误 等级别。
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

format参数中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s用户输出的消息

logger对象配置

import logging

logger = logging.getLogger()

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler(‘test.log‘,encoding=‘utf-8‘) 

# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler() 

formatter = logging.Formatter(‘%(asctime)s - %(name)s - %(levelname)s - %(message)s‘)

fh.setLevel(logging.DEBUG)

fh.setFormatter(formatter)
ch.setFormatter(formatter) 

logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)

logger.debug(‘logger debug message‘)
logger.info(‘logger info message‘)
logger.warning(‘logger warning message‘)
logger.error(‘logger error message‘)
logger.critical(‘logger critical message‘)

logging库提供了多个组件:Logger、Handler、Filter、Formatter。
Logger对象提供应用程序可直接使用的接口,
Handler发送日志到适当的目的地,
Filter提供了过滤日志信息的方法,
Formatter指定日志显示格式。
另外,可以通过:logger.setLevel(logging.Debug)设置级别,
当然,也可以通过fh.setLevel(logging.Debug)单对文件流设置某个级别。

end

2018-4-23

原文地址:https://www.cnblogs.com/tielemao/p/8921919.html

时间: 2024-10-26 19:18:51

铁乐学python26_hashlib+configparser+logging模块的相关文章

hashlib,configparser,logging模块

一.常用模块二 hashlib模块 hashlib提供了常见的摘要算法,如md5和sha1等等. 那么什么是摘要算法呢?摘要算法又称为哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示). 注意:摘要算法不是一个解密算法.(摘要算法,检测一个字符串是否发生了变化) 应涂:1.做文件校验 2.登录密码 密码不能解密,但可以撞库,用'加盐'的方法就可以解决撞库的问题.所有以后设置密码的时候要设置的复杂一点. 1 import hashlib 2

8.模块介绍 time &amp;datetime模块 random os sys shutil json &amp; picle shelve xml处理 yaml处理 configparser hashlib subprocess logging模块 re正则表达式

本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configparser hashlib subprocess logging模块 re正则表达式 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.p

常用模块(hashlib,configparser,logging)

hashlib hashlib 摘要算法的模块md5 sha1 sha256 sha512摘要的过程 不可逆能做的事:文件的一致性检测用户的加密认证 单纯的md5不够安全 加盐处理 简单的盐可能被破解 且破解之后所有的盐都失效 动态加盐 md5 = hashlib.md5() # 选择摘要算法中的md5类进行实例化,得到md5_obj md5.update(b'how to use md5 in python hashlib?') # 对一个字符串进行摘要 print(md5.hexdigest

python全栈开发【第十一篇】Python常用模块三(hashlib,configparser,logging)

hashlib模块 hashlib提供了常见的摘要算法,如md5和sha1等等. 那么什么是摘要算法呢?摘要算法又称为哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示). 注意:摘要算法不是一个解密算法.(摘要算法,检测一个字符串是否发生了变化) 应涂:1.做文件校验 2.登录密码 密码不能解密,但可以撞库,用'加盐'的方法就可以解决撞库的问题.所有以后设置密码的时候要设置的复杂一点. #用户密码 import hashlib # md5

铁乐学Python_Day34_Socket模块2和黏包现象

铁乐学Python_Day34_Socket模块2和黏包现象 套接字 套接字是计算机网络数据结构,它体现了C/S结构中"通信端点"的概念. 在任何类型的通信开始之前,网络应用程序必須创建套接字. 可以将它们比作成电话插孔,没有它将无法进行通信. 套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个进程)与另一个运行的程序进行通信. 这就是所谓的进程间通信(Inter Process Communication, IPC). 有两种类型的套接字:基于文件的和面向网

configparser模块 logging模块

configparser模块 固定格式的配置文件 有一个对应的模块去帮你做这个文件的字符串处理 config = configparser.Configparser() config.read(“example.ini”) logging模块 功能 1.日志格式的规范 2.操作的简化 3.日志的分级管理 logging  不能帮你做的事情 自动生成你要打印的内容 需要程序员自己在开发的时候定义好: 在哪些地方需要打印,要打印的内容是什么,内容的级别 logging模块的使用: 普通配置型 简单的

序列化 ,hashlib ,configparser ,logging ,collections模块

# 实例化 归一化 初始化 序列化 # 列表 元组 字符串# 字符串# .......得到一个字符串的结果 过程就叫序列化# 字典 / 列表 / 数字 /对象 -序列化->字符串# 为什么要序列化 # 1.要把内容写入文件 序列化 # 2.网络传输数据 序列化# 字符串-反序列化->字典 / 列表 / 数字 /对象 # 方法# dic = {'k':'v'}# str_dic = str(dic)# print(dict(str_dic))# print([eval(str_dic)])# e

25.Python序列化模块,hashlib模块, configparser模块,logging模块,异常处理

一.序列化模块 什么叫序列化——将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化. 比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来.但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中.你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?没错序列化的过程就是从dic 变成str(di

python logging模块配置方法浅析

以下功能函数配置logging模块.它们位于logging.config模块中.它们的使用是可选的 - 可以使用这些功能函数配置logging模块:或者通过调用主API(logging中定义)并且定义在logging或logging.handlers中定义的handlers. logging.config.dictConfig(config): 从字典获取logging配置. logging.config.fileConfig(fname, defaults=None, disable_exis