数据库--用户管理, 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开始
原文地址:https://www.cnblogs.com/lucky75/p/11204183.html