mysql用戶管理 !這是dba的活兒!,但是萬一公司沒有dba? mysql用戶指的是什麼? 我們每一次在操作前都需要指定賬號和密碼,這個賬號就是mysql的用戶; 為什麼要管理? 一個公司不可能只有一個工程師,大公司,不不僅有很多工程師 還有很多不同部門,但是資料庫伺服器只有一個,大家都要訪問, ...
mysql用戶管理
!這是dba的活兒!,但是萬一公司沒有dba?
mysql用戶指的是什麼?
我們每一次在操作前都需要指定賬號和密碼,這個賬號就是mysql的用戶;
為什麼要管理?
一個公司不可能只有一個工程師,大公司,不不僅有很多工程師 還有很多不同部門,但是資料庫伺服器只有一個,大家都要訪問,這就涉及到用戶和許可權問題了
一個工程師對應一個賬戶,
哪些工程師可以操作哪些資料庫,哪些表,甚至哪些欄位,都可以進行控制,例如,騰訊,有qq和微信不同項目,qq的工程師,就不應該去訪問微信項目的數據;
mysql是如何管理的
mysql本質上是一款cs軟體,它具備用戶認證!
我們有沒有做過用戶認證呢? ATM! 購物車,都做過,
我們是如何實現的?寫入文件,mysql也是一樣的,
只不過它把文件稱為表
那麼要怎麼添加賬戶呢?
把用戶信息寫入表中就可以了
許可權相關表
來看看它都把數據放在哪個表中了!
自帶的mysql資料庫,四個表用於存儲賬戶信息以及許可權
user
db
table_priv
columns_priv
許可權優先順序
user->db->table_priv->columns_priv
select *from user;
#由於欄位較多 以表格形式展示 會比較亂,可以添加\G來縱向顯示
select *from user\G;
內置root賬戶欄位信息解析
創建賬號語句
create user 用戶名@"ip地址" "identified" by 密碼;
create user tom@"192.168.101" identified by "123";
該語句錶面tom只能在101機器上使用,別的機器就無法登錄
用%可以表示在任意機器可用
註意:該方式創建的賬號沒有任何許可權 所以瞭解即可
授權語句
授權:
授權語句執行時如果賬號不存在會自動創建賬號 所以更推薦使用
註意:預設只有root才能為其他賬號授權
grant all on *.* to tom@"localhost" identified by "123";
#該語句中的all 增刪改查所有許可權 但是不包括grant許可權
#*.* 表示任何資料庫 任何表 存儲在user表
grant all on *.* to toms@"%" identified by "123";
# host 為% 表示 該賬戶可以在任何主機上登錄但是不包括localhost
grant all on *.* to toms@"localhost" identified by "123";
# 繼續執行 上述語句保證localhost也可以登錄該賬戶
grant all on db.* to tom@"localhost" identified by "123"
#db.* 該用戶可以操作db資料庫的任何表 存儲在 db表
grant all on db.t1 to tom@"localhost" identified by "123"
#db.* 該用戶可以操作db資料庫的t1表 存儲在 table_privi表
grant select(id) on db.t1 to tom@"localhost" identified by "123"
#精確到欄位 和 操作級別
#該用戶只能查詢 db下的t1表
grant all on *.* to tom@"localhost" identified by "123" with grant option;
#with grant option 表示該賬戶可以將許可權授予其他用戶
REVOKE all privileges [column] on db.table from user@"host";
#收回許可權
drop user@"host"
#刪除用戶
flush privileges;
#刷新許可權表 一些時候許可權信息可能會有所延遲 可以執行該語句立即刷新許可權信息
pymysql模塊
pymysql是python提供的一個mysql客戶端模塊,用於與mysql伺服器建立連接,發送查詢,並獲取結果等;
基本使用:
import pymysql
# 1.建立連接
try:
conn = pymysql.connect(host="127.0.0.1",port=3306,user="root",password="",db="day46",)
print("連接伺服器成功!")
#2.獲取游標對象
cursor = conn.cursor()
#3.執行sql語句
count = cursor.execute("select *from user")
print("結果數量: %s" % count)
# 提取結果
# print(cursor.fetchall())
# print(cursor.fetchone())
# print(cursor.fetchmany(1))
# 移動游標位置 相對當前位置
cursor.scroll(1,"relative")
cursor.scroll(-1, "relative")
print(cursor.fetchone())
# 移動游標位置 使用絕對位置
cursor.scroll(0, "absolute")
print(cursor.fetchone())
print(cursor.fetchall())
# 註意 游標移動到末尾後無法在讀取到數據 若需重覆讀取數據,需要使用scroll來移動游標
except Exception as e:
print("連接伺服器失敗.....")
print(type(e),e)
finally:
if cursor:
cursor.close()
print("關閉游標")
if conn:
conn.close()
print("關閉鏈接")
上述代碼中 fetch 相關函數返回值類型為元組,使用起來不夠方便,我們可以在創建游標時指定游標類型為字典類型像這樣:
cursor = conn.cursor(pymysql.cursors.DictCursor)
sql註入攻擊
何為sql註入
sql註入指的是,用戶在輸入數據時,按照sql的語法,來編寫帶有攻擊目的的sql語句,並插入到原始語句中執行.
例如:登錄功能,需要用戶輸入用戶名和密碼
正常的一個登錄功能代碼如下:
try:
conn = pymysql.connect(host="127.0.0.1",port=3306,user="root",password="",db="day46",)
print("連接伺服器成功!")
cursor = conn.cursor(pymysql.cursors.DictCursor)
user = input("username:")
password = input("password:")
count = cursor.execute("select *from user where name = '%s' and password = '%s'" % (user,password))
if count:
print("登錄成功!")
else:
print("登錄失敗!")
except Exception as e:
print(type(e),e)
finally:
if cursor:cursor.close()
if conn: conn.close()
上述代碼有被註入攻擊的危險
嘗試在用戶名中輸入以下內容,密碼隨意
jerry' — ass
或者連用戶名都不用寫
' or 1 = 1 -- asaa
解決方案:
1.客戶端在發送sql給伺服器前進行re判斷
這樣的問題在於一些程式可以模擬客戶端直接發送請求給伺服器
2.在伺服器端將sql交給mysql是作進一步處理,相關的代碼其實pymysql已經做了封裝
我們只要保證不要自己來拼接sql語句即可,將拼接參數操作交給pymysql.
try:
conn = pymysql.connect(host="127.0.0.1",port=3306,user="root",password="",db="day46",)
print("連接伺服器成功!")
cursor = conn.cursor(pymysql.cursors.DictCursor)
user = input("username:")
password = input("password:")
sql = "select *from user where name = %s and password = %s"
print(sql)
count = cursor.execute(sql,(user,password)) # 參數交給模塊
if count:
print("登錄成功!")
else:
print("登錄失敗!")
except Exception as e:
print(type(e),e)
finally:
if cursor:cursor.close()
if conn: conn.close()
增刪改
import pymysql
# 1.建立連接
try:
conn = pymysql.connect(host="127.0.0.1",port=3306,user="root",password="",db="day46",)
print("連接伺服器成功!")
cursor = conn.cursor(pymysql.cursors.DictCursor)
#增
#sql = "insert into user values(null,%s,%s,%s)"
#count = cursor.execute(sql,("tom","man","123321"))
# 一次性插入多條記錄
#sql = "insert into user values (null,%s,%s,%s)"
#count = cursor.executemany(sql, [("周芷若","woman","123"), ("趙敏","woman","321")])
#刪
# count = cursor.execute("delete from user where id = 1")
#改
count = cursor.execute("update user set name = '劉大炮' where id = 1")
if count:
print("執行成功!")
else:
print("執行失敗!")
# 獲取最新的id
# print(cursor.lastrowid)
except Exception as e:
print(type(e),e)
finally:
if cursor:cursor.close()
if conn: conn.close()
強調:pymysql 對於數據的增刪改預設都不會生效,必須調用鏈接對象的commit()來提交修改 或者在創建鏈接對象時指定為自動提交;
conn.commit()
#或者創建鏈接對象時指定為自動提交
conn = pymysql.connect(host="127.0.0.1",port=3306,user="root",password="",db="day46",autocommit=True)