!這是dba的活兒!,可是萬一公司沒有dba?python
mysql用戶指的是什麼?mysql
咱們每一次在操做前都須要指定帳號和密碼,這個帳號就是mysql的用戶;sql
爲何要管理?數據庫
一個公司不可能只有一個工程師,大公司,不不只有不少工程師 還有不少不一樣部門,可是數據庫服務器只有一個,你們都要訪問,這就涉及到用戶和權限問題了服務器
一個工程師對應一個帳戶,微信
哪些工程師能夠操做哪些數據庫,哪些表,甚至哪些字段,均可以進行控制,例如,騰訊,有qq和微信不一樣項目,qq的工程師,就不該該去訪問微信項目的數據;ide
mysql本質上是一款cs軟件,它具有用戶認證!函數
咱們有沒有作過用戶認證呢? ATM! 購物車,都作過,fetch
咱們是如何實現的?寫入文件,mysql也是同樣的,code
只不過它把文件稱爲表
那麼要怎麼添加帳戶呢?
把用戶信息寫入表中就能夠了
來看看它都把數據放在哪一個表中了!
自帶的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是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語句,並插入到原始語句中執行.
例如:登陸功能,須要用戶輸入用戶名和密碼
正常的一個登陸功能代碼以下:
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)