2016-09-20 155 views
0

我正在爲網站創建一個更改密碼頁面,該頁面要求新密碼和當前密碼。使用scrypt庫對舊密碼進行哈希和醃製,然後與存儲在sqlite3數據庫中的密碼進行比較,如果這些密碼匹配,則會對新密碼進行散列並更新數據庫。但是我執行update命令時遇到困難,因爲它會拋出sqlite3.OperationalError:無法識別的標記:「\」錯誤。在執行語句目前有以下代碼:Python Sqlite3數據庫表未更新

c.execute("UPDATE users SET password = \'{0}\' WHERE memberID = \'{1}\'".format(newPas, memID)) 

最初我們認爲這個錯誤已經造成新的密碼本身「的字符串由於格式到的存在」的可能性,所以這是運行再次如下:

c.execute("UPDATE users SET password = \"{0}\" WHERE memberID = \"{1}\"".format(newPas, memID)) 

這成功運行,但實際上並沒有改變數據庫中的任何東西。我們也嘗試創建一個查詢字符串,然後執行該字符串。

query = "UPDATE users SET password = {0} WHERE memberID = {1}".format(newPas, memID) 
c.execute(query) 

這引起了sqlite3.OperationalError:近「'\ XA1 \ X91 \ x9f \ X88 \ xfb的\ X81 \ X12 \ XD 4 \ XC2 \ xf9 \ XCE \ x91y \ XF0/\ XE1 *#\ x8aj \ xc7 \ X1D \ XD3 \ X91 \ X14 \ XCB \ XA4 \ xabaP [\ X02 \ X1D \ X1B \ xabr \ xc7 \ XE4 \ XEE \ X19 \ x80c \ x8e | \ xc0S \ xaaX \ XC6 \ X04 \ XAB \ X08 \ x9b \ x8e \ xd7zB \ xc6 \ x84 [\ xfb \ xbc \ x8d \ xfc'「:語法錯誤。我相信這是由於密碼中存在'和「字符引起的,但我不確定如何解決此問題,因爲這些問題是通過散列過程添加的,因此刪除它們會更改密碼。 我想要的密碼想補充的是:

b'\xa1\x91\x9f\x88\xfb\x81\x12\xd4\xc2\xf9\xce\x91y\xf0/\xe1*#\x8aj\xc7\x1d\xd3\x91\x14\xcb\xa4\xabaP[\x02\x1d\x1b\xabr\xc7\xe4\xee\x19\x80c\x8e|\xc0S\xaaX\xc6\x04\xab\x08\x9b\x8e\xd7zB\xc6\x84[\xfb\xbc\x8d\xfc' 

我想知道如果任何人都可以分享一些見解爲什麼不順心的「\」字符或爲什麼不更新數據庫,並指出我在正確的方向如果你需要更多的信息或代碼片段,或者只是想對我大吼,請不要猶豫!先謝謝你:)

+2

一對夫婦更一般的東西。你不應該用這種方式格式化查詢,你應該使用'sqlite'佔位符,例如'query =「UPDATE users SET password =?WHERE memberID =?」'然後'c.execute(query,(newPas,memID))'。另外,我假設你提交()'變化?我不知道這是否會解決您的問題,但是您絕對不應該使用'format'來創建查詢,因爲您可能需要sql注入。 – roganjosh

+1

我希望你沒有[小巴比表](https://xkcd.com/327/)作爲會員。 –

+0

請注意,上面代碼片段中的(其中一個)問題正在將一個「bytes」對象格式化爲查詢字符串。直接將它直接傳遞給'format()'將有效地將內聯字節對象的[representation](http://stackoverflow.com/questions/7784148/understanding-repr-function-in-python)內聯到查詢,這絕對不是你想要的。更不用說,像這樣的值格式化查詢字符串是一個巨大的禁忌。正如其他人已經指出的那樣,使用佔位符。 –

回答

0

幾件事情與您的代碼:

  1. 你。不應該使用format來構建這樣的查詢,這會讓你很容易進行SQL注入,並且儘管在這種情況下你可能會對輸入進行消毒,但這是一個糟糕的習慣,它會咬你。數據庫實際生效,這就是爲什麼你的第二個查詢沒有拋出錯誤,但同樣不合適d不會對數據庫進行任何更改。

這個查詢的正確格式將是:

conn = sqlite3.connect('my_db.db') 
c = conn.cursor() 

query = "UPDATE users SET password = ? WHERE memberID = ?" 
c.execute(query, (newPas, memID)) 

conn.commit() # To finalise the alteration 

作爲邊注,光標預計在此情況下的元組,所以共同的絆腳石來傳遞單值時:

query = "UPDATE users SET password = ? WHERE memberID = 'abc'" 
c.execute(query, (newPas)) # Throws "incorrect number of bindings" error 

# Use this instead i.e. pass single value as a tuple 
c.execute(query, (newPas,)) 

你可以使用format在查詢中創建變量字段名,因爲佔位符在此情況下,允許:

fields = ['a', 'b', 'c'] 

query = "UPDATE users SET {} = ?".format(random.choice(fields)) 
除了

用它來幫助你建立大的查詢哪裏,如果你的代碼改變這將是乏味的手動輸入所有的佔位符,並且很難保證你有正確的數字:

my_list = ['a', 'b',...., n] 
placeholders = ', '.join(['?' for item in my_list]) 

query = "INSERT .... VALUES = ({})".format(placeholders) 
1

你應該使用這樣的參數化查詢:

c.execute(「」「UPDATE users SET password =? ?WHERE MEMBERID = 「;」」,(newPas,memID))

它將允許避免像SQL-注入討厭的東西

+0

這只是我評論的一面鏡子,不知道它是否實際上解決了問題... – roganjosh

+0

@roganjosh當我寫答案時,我沒有看到你的評論。對不起。 – Nurjan