• python连接数据库(pymysql)及数据库加密


    内容:

    1.pymysql介绍

    2.pymysql基本使用

    3.数据库加密

    参考:http://www.cnblogs.com/wupeiqi/articles/5713330.html

    1.pymysql介绍

    pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同,在python3 中以及不支持MySQLdb这个模块了,所有我们现在只用学习pymysql即可

    安装:

    1 pip3 install pymysql

    2.pymysql基本使用

    (1)预备知识:SQL

    sql详细:http://www.cnblogs.com/wyb666/p/9017402.html

    1 数据库通过 SQL 来操作数据
    2 SQL (结构化查询语言)-> 操作数据库的接口 也就是操作数据库的方法
    3 增加数据  删除数据  修改数据  查询数据
    4 CRUD
    5 create retrieve update delete

    (2)使用pymysql操作MySQL的大致流程

     1 import pymysql
     2   
     3 # 创建连接
     4 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
     5 # 创建游标
     6 cursor = conn.cursor()
     7   
     8 # 执行SQL,并返回收影响行数
     9 effect_row = cursor.execute("update hosts set host = '1.1.1.2'")
    10   
    11 # 执行SQL,并返回受影响行数
    12 #effect_row = cursor.execute("update hosts set host = '1.1.1.2' where nid > %s", (1,))
    13   
    14 # 执行SQL,并返回受影响行数
    15 #effect_row = cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)])
    16   
    17   
    18 # 提交,不然无法保存新建或者修改的数据
    19 conn.commit()
    20   
    21 # 关闭游标
    22 cursor.close()
    23 # 关闭连接
    24 conn.close()

    (3)对以上过程的封装

    看到这里你可能会好奇,以上那种用法不是蛮好吗,直接从上到下执行代码,干嘛还要封装,封装是为了代码的逻辑性更强,另外代码具有更多的可拓展性,我们自己封装直接封装成函数即可,不必封装成类(那样也可以不过太麻烦太复杂了),当然我们也可以使用别人的封装(后面要学到的SQLAlchemy就是一种简单的封装,其将对数据库的操作封装成对类的操作)

    SQL操作无非可分为以下几种:

    • 创建库表
    • 增删改查数据

    所以我将这些功能封装成相应的函数即可,如下所示:

      1 # __author__ = "wyb"
      2 # date: 2018/8/20
      3 import pymysql
      4 
      5 
      6 # 创建数据库中的表
      7 def create(conn):
      8     # 注意 CREATE TABLE 这种语句不分大小写
      9     sql_create = '''
     10     CREATE TABLE `users` (
     11         `id`    INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
     12         `username`    VARCHAR(200) NOT NULL UNIQUE,
     13         `password`    TEXT NOT NULL,
     14         `email`    TEXT
     15     )
     16     '''
     17     # 用 execute 执行一条 sql 语句
     18     conn.execute(sql_create)
     19     print('创建成功')
     20 
     21 
     22 # 向数据库中插入数据
     23 def insert(conn, username, password, email):
     24     sql_insert = '''
     25     INSERT INTO
     26         users(username,password,email)
     27     VALUES
     28         (%s, %s, %s);
     29     '''
     30     # 参数拼接要用 %s,execute 中的参数传递必须是一个 tuple 类型
     31     conn.execute(sql_insert, (username, password, email, ))
     32     print('插入数据成功')
     33 
     34 
     35 # 查询数据
     36 def select(conn):
     37     sql = '''
     38     SELECT
     39         *
     40     FROM
     41         users
     42     '''
     43     # 这是读取数据的套路
     44     conn.execute(sql)
     45     res = conn.fetchall()
     46     print("所有数据如下: ")
     47     for row in res:
     48         print(row)
     49 
     50 
     51 # 删除数据
     52 def delete(conn, user_id):
     53     sql_delete = '''
     54     DELETE FROM
     55         users
     56     WHERE
     57         id=%s
     58     '''
     59     # 注意, execute 的第二个参数是一个 tuple
     60     # tuple 只有一个元素的时候必须是这样的写法
     61     conn.execute(sql_delete, (user_id,))
     62     print("删除数据成功")
     63 
     64 
     65 # 更新数据
     66 def update(conn, user_id, email):
     67     sql_update = '''
     68     UPDATE
     69         `users`
     70     SET
     71         `email` = %s
     72     WHERE
     73         `id`= %s
     74     '''
     75     conn.execute(sql_update, (email, user_id))
     76     print("更新数据成功")
     77 
     78 
     79 # 主程序
     80 def main():
     81     # 指定数据库名字并打开 -> 没有会自动创建
     82     # 创建连接
     83     conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='wyb')
     84     print("打开数据库wyb")
     85     # 创建游标
     86     cursor = conn.cursor()
     87 
     88     # create 创建表结构 -> 注意创建表只能创建一次 创建已创建的表会报错
     89     # create(cursor)
     90 
     91     # insert 插入数据   -> 注意插入一次后下面的数据就不能再插入 因为用户名有限制(unique)
     92     # insert(cursor, 'wpz', '123', 'tggh@b.c')
     93 
     94     # delete 删除数据
     95     # delete(cursor, 1)
     96 
     97     # update 更新数据
     98     # update(cursor, 4, 'woz_wyb@qq.com')
     99     # select 查询数据
    100     # select(cursor)
    101 
    102     # 最后提交: 必须用 commit 函数提交你的修改 否则你的修改不会被写入数据库
    103     conn.commit()
    104     # 用完数据库要关闭
    105     cursor.close()
    106     conn.close()
    107 
    108 
    109 if __name__ == '__main__':
    110     main()

    先运行上述代码中的create函数,然后操作如下:

    可以明显看到现在已经通过程序建立了数据库的表结构,接下来使用其他函数体验一下增删改查(insert、delete、update、select),每个函数运行完后在终端上

    使用select * from users;查看表中数据变化

    (4)fetch数据类型

    默认获取的数据是元祖类型,如果想要或者字典类型的数据,即:

     1 import pymysql
     2   
     3 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
     4   
     5 # 游标设置为字典类型
     6 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
     7 r = cursor.execute("call p1()")
     8   
     9 result = cursor.fetchone()
    10   
    11 conn.commit()
    12 cursor.close()
    13 conn.close()

    3.数据库加密

    众所周知,数据库加密是十分重要的,因为数据库会存储一些敏感信息,比如密码,即使我们的程序没有任何的安全漏洞不会被黑客攻击,但是程序所在的服务器可能有安全漏洞,我们使用的数据库软件可能会有漏洞,因此要对数据中的一些敏感信息(比如密码)进行加密存储

    (1)数据库加密方法

    常见的加密算法有对称加密、非对称加密以及hash算法,一般数据库中敏感信息使用hash算法加密即可

    常见的Hash算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1

    (2)加密实例

    注册登录验证(密码加密):

     1 class User(Model):
     2     """
     3     User 是一个保存用户数据的 model
     4     现在只有两个属性 username 和 password
     5     """
     6     def __init__(self, form):
     7         self.id = form.get('id', None)
     8         self.username = form.get('username', '')
     9         self.password = form.get('password', '')
    10 
    11     # 加盐加密
    12     @staticmethod
    13     def salted_password(password, salt="`1234567890~!@#$%^&*()-=[];'/,./ZXCVBNSADFYWQET"):
    14         # salt:  "`1234567890~!@#$%^&*()-=[];'/,./ZXCVBNSADFYWQET"
    15         def md5hex(ascii_str):
    16             return hashlib.md5(ascii_str.encode('ascii')).hexdigest()
    17 
    18         # 普通加密
    19         hash1 = md5hex(password)
    20         # 加盐加密
    21         hash2 = md5hex(hash1 + salt)
    22         return hash2
    23 
    24     # 注册
    25     def validate_register(self):
    26         pwd = self.password
    27         self.password = self.salted_password(pwd)
    28         # 用户名已存在就不允许注册 否则可以注册
    29         if User.find_by(username=self.username) is None:
    30             self.save()
    31             return self
    32         else:
    33             return None
    34 
    35     # 登录
    36     def validate_login(self):
    37         u = User.find_by(username=self.username)
    38         if u is not None:
    39             return u.password == self.salted_password(self.password)
    40         else:
    41             return False
    42 
    43     # 修改密码
    44     def change_pwd(self, form):
    45         # 输入两次旧密码不一样
    46         pwd1 = form.get("pwd1", "")
    47         pwd2 = form.get("pwd2", "")
    48         if pwd1 != pwd2:
    49             res = {
    50                 "msg": "两次输入的旧密码不一样",
    51                 "data": None,
    52             }
    53             return res
    54 
    55         # 输入的旧密码正确就重置 否则就不重置
    56         new_pwd = form.get("new_pwd", "")
    57         if self.salted_password(pwd1) == self.password:
    58             self.password = self.salted_password(new_pwd)
    59             self.save()
    60             res = {
    61                 "msg": "重置密码成功",
    62                 "data": self,
    63             }
    64         else:
    65             res = {
    66                 "msg": "输入的旧密码错误!",
    67                 "data": None,
    68             }
    69         return res

    注意:上述代码不是完整代码,但不用关心其他细节,只关心具体的加密以及验证方法

    上述代码的加密逻辑:

    使用python的hashlib加密模块,先用普通的md5的hash算法直接对密码进行加密,然后再对加密后的密文加上盐再进行加密

    验证逻辑:

    将用户输入的密码同样使用上述方法加密,如果最后结果和数据库中存的结果是一样的,那么就通过验证,否则验证失败

    由此,可以得出结论:

    假设密码存入数据库均经过上述过程中的hash加密,那么除了用户本人没有人会知道到底密码是什么(当然黑客破解也不是不行,但破解难度极大),所以当忘记密码时一般都不能直接找回密码,而是通过回答密保问题(或其他方式)来修改密码,因为除了用户自己没有人知道密码是什么

  • 相关阅读:
    一百多套开发视频教程的下载地址
    http://blog.csdn.net/chlele0105/article/details/9056951
    http://kb.cnblogs.com/page/541862/
    Linux版本选择
    2015-2016规划
    PHP 类的继承一些知识点汇总
    PHP面向对象的基本属性分析
    PHP中的魔术方法总结 :
    PHP字符串常用操作函数
    php八中数据类型以及相互转换
  • 原文地址:https://www.cnblogs.com/wyb666/p/9489373.html
Copyright © 2020-2023  润新知