zoukankan      html  css  js  c++  java
  • 数据库--用户管理, pymysql

    1.用户管理

    • 主要是为了控制权限,让不同开发者,仅能操作属于自己的业务范围内的数据

    创建MySQL账户

    账户中涉及的三个数据:

    1. 账户名
    2. 密码
    3. ip地址:用于限制某个账户只能在哪些机器上登录
    # 创建用户
    create user 用户名@主机地址 identified by '密码';
    # 删除用户
    drop user 用户名@主机地址;
    
    # 注意:操作用户只能由root账户来进行
    # 刚注册的用户没有任何权限,包括登录权限也没有
    
    可以通过查看user表查看用户,G列查看
    

    权限管理

    涉及到的表(在mysql库下)

    user	与用户相关的信息
    db		用户的数据库权限信息
    talbes_priv	用户的表权限
    columns_priv	用户的字段权限
    

    语法:

    # 语法
    grant all on *.* to 用户名@主机地址 identified by "密码";
    # all:对所有的字段增删改查
    # *.*:所有库的所有表
    # 注意:# 如果用户名不存在,则自动创建新用户,推荐使用
    # localhost是一个指向127.0.0.1的域名
    
    
    # 创建在所有库有所有权限的用户,但是并没有操作用户的权限
    grant all on *.* to haha@localhost identified by '123';		# 可以在user表中查看
    
    # 创建在某个库有所有权限的用户
    grant all on day42 to haha1@localhost identified by '123';	# 可以在user,db中查看
    
    # 创建在某个表有所有权限的用户
    grant all on day42.table1 to haha2@localhost identified by '123';	# 可以在user,tables_priv中查看
    
    # 创建在某个字段有读,更新权限的用户
    grant select(name), update(name) on day42.table1 to haha3@localhost identified by '123';	# 可以在user,talbes_priv,columns_priv表中查看
    
    # with grant option 表示可以将他拥有的权限授予其他用户
    grant all on *.* to root1@localhost identified by '123' with grant option;
    
    
    # 收回权限
    revoke all on *.* from 用户名@主机地址;
    
    
    # 授予某个用户,可以在任何主机上登录
    grant all on *.* to haha4@"%" identified by "123";	# 本机无法登陆
    # 再创建一个本机的,并不是给上面的加权限,而是又新建了一个用户也叫haha4,可以在user表中看到
    group all on *.* to haha4@'localhost' identified by "123";
    
    

    注意:

    这些操作在敲完之后一定要刷新

    flush privileges
    

    2.可视化客户端

    ​ navicat

    ​ mysql workbench

    3.pymysql

    • 是一个第三方模块,帮我们封装了,建立连接,用户认证,sql的执行以及数据的获取

    基本使用

    import pymysql
    
    # 1. 连接服务器,获取连接对象(本质上就是封装好的socket)
    conn = pymysql.connect(
    	host = '127.0.0.1',	# 如果是本机,可以不填
    	port = 3306,	# 如果没改过默认的端口,可以不填
    	user = 'root',	# 必填,不会走mysql的配置文件
    	password = '123',	# 必填
    	database = 'day42'	# 必填
    	)
    
    # 2. 通过连接拿到游标对象
    # 默认的游标返回的是元祖类型,不方便查看使用,需要更换字典类型的游标
    c = conn.cursor()	# 元祖	
    c = conn.cursor(pymysql.cursors.DictCursor)	# 字典
    
    # 3. 执行sql语句
    sql = 'select * from table1'
    res = c.execute(sql)
    # 各种语句返回的都是结果的数量,比如查看到了一条就返回1,修改了一条返回1之类
    
    # 4. 提取结果,类似于迭代,只能提取一次
    print(res)	
    print(c.fetchall())	# 提取所有
    # print(c.fetchmany(2))	# 提取多条
    # print(c.fetchone())	# 提取一条
    
    # 5. 关闭连接
    c.close()	# 先关闭游标
    conn.close()
    
    # 如果想要再重复读取,需要移动指针,参数1是移动的位置,mode指定相对或绝对,默认是相对
    c.scroll(1, mode='absolute')	# 绝对,从头部开始计算
    

    sql注入攻击

    一些程序员,在输入数据时,按照sql的语法规范,提交了用于攻击性目的的数据

    案例:登录

    import pymysql
    # 这些固定用法可以写到python配置文件中
    conn = pymysql.connect(
        host = "127.0.0.1", 
        port = 3306,
        user = "root",
        password = "111",
        database = "day42",
    )
    c = conn.curssor(pymysql.cursors.DictCursor)
    
    name = input('name:')
    pwd = input('pwd:')
    
    sql = 'select * from user where name = "%s" and pwd = %s' % (name, pwd)
    
    res = c.execute(sql)
    if res:
        print('登录成功')
    else:
        print('登录失败')
    
    c.close()
    conn.close()
    
    # 这个程序看上去没什么问题,但是当有程序员恶意输入时就会出现问题,比如:
    # 帐号输入 " or 1 = 1; --  密码随意输入比如1,也一样可以登录
    # 这是因为实际上给mysql输入的内容为
    select * from user where name = "" or 1 = 1; -- " and pwd = 1
    # 而--就是注释的意思,后面的代码不会执行,所以前面的语句因为有1=1所以会输出数据,导致错误登录
    # 注意:注释-- 后面需要有一个空格
        
    

    如何避免这个问题

    在服务器段执行sql语句以前做sql的验证,判断有没有一些关键的代码,比如drop 等等

    之所以不在客户端做验证,是因为在传输过程中程序员依然可以抓取数据进行更改

    pymysql已经封装了这个过程,只需要将参数交给pymysql来做拼接即可

    需要修改的代码为:

    # 将拼接参数交给pymysql
    sql = 'select * from user where name = %s and pwd = %s'
    
    res = c.execute(sql, (name, pwd))
    

    事务

    • pymysql默认执行了start transaction开启了事务
    import pymysql
    conn = pymysql.connect(
    	...# 重复的配置代码就不写了,上同
        # autocommit = True	# 这是开启自动提交,默认是False,一般不要改这个,自己手动提交就好了,更加灵活
        
    )
    c = conn.cursor(pymysql, coursors.DictCursor)
    
    name = input('name:')
    pwd = input('pwd:')
    
    sql1 = 'select * from user where name = %s'
    
    if c.execute(sql1, (name,)):	# 一定要提交元组
        print('用户名已存在!')
    else:
        sql2 = 'insert into user values(%s, %s)'
        if c.execute(sql2, (name, pwd)):
            print('注册成功')
            conn.commit()	# 调用pymysql封装的连接对象的提交函数,也可以在配置文件中进行修改
        else:
            print('注册失败')
            
    c.close()
    conn.close()
    

    调用储存过程

    # mysql中创建名为add1的储存过程
    delimiter |
    create procedure add1(in a int, in b int, out c int)
    begin
    set c = a + b;
    end|
    delimiter;
    
    # 配置文件不变
    c.callproc('add1', (30, 40, 12138))# @_add1_0, @_add1_1, @_add1_2
    c.execute('select @_add1_2')
    print(c.fetchone())
    
    # 调用储存过程时,传入的参数会自动定义成变量
    # 变量的命名方式是	@_过程的名称_参数的索引  索引从0开始
    
  • 相关阅读:
    1011. A+B和C (15)
    1010. 一元多项式求导 (25)
    1009. 说反话 (20)
    1007. 素数对猜想 (20)
    1008. 数组元素循环右移问题 (20)
    1006. 换个格式输出整数 (15)
    1005. 继续(3n+1)猜想 (25)
    算法学习(八)
    算法学习(七)
    算法学习(六)
  • 原文地址:https://www.cnblogs.com/lucky75/p/11204183.html
Copyright © 2011-2022 走看看