15

この文字列:

"CREATE USER %s PASSWORD %s", (user, pw)

常に次のように展開されます:

CREATE USER E'someuser' PASSWORD E'somepassword'

誰でも理由を教えてもらえますか?

編集: 上記の展開された文字列は、データベースがエラー メッセージで返す文字列です。postgres データベースにアクセスするために psycopg2 を使用しています。実際のコードは次のようになります。

conn=psycopg2.connect(user=adminuser, password=adminpass, host=host)
cur = conn.cursor()

#user and pw are simple standard python strings the function gets as parameter
cur.execute("CREATE USER %s PASSWORD %s", (user, pw))
conn.commit()
4

4 に答える 4

17

モジュールAsIsからpsycopg を使用して識別子を postgresql に渡すにはextensions

from psycopg2.extensions import AsIs
import psycopg2
connection = psycopg2.connect(database='db', user='user')
cur = connection.cursor()
cur.mogrify(
    'CREATE USER %s PASSWORD %s', (AsIs('someuser'), AsIs('somepassword'))
    )
'CREATE USER someuser PASSWORD somepassword'

これは、次のような句に条件を渡す場合にも機能しますorder by

cur.mogrify(
    'select * from t order by %s', (AsIs('some_column, another column desc'),)
    )
'select * from t order by some_column, another column desc'
于 2012-12-15T10:47:28.597 に答える
10

OPの編集により、彼がPostgreSQLを使用していることが明らかになったため、そのドキュメントは関連性があり、次のように述べています。

PostgreSQLは、SQL標準の拡張である「エスケープ」文字列定数も受け入れます。エスケープ文字列定数は、開始一重引用符の直前に文字E(大文字または小文字)を書き込むことによって指定されます(例:E'foo')。

言い換えると、psycopgは、文字列のエスケープ文字列定数を正しく生成しています(したがって、ドキュメントにも次のように記載されています。

エスケープ文字列内で、バックスラッシュ文字()はCのようなバックスラッシュエスケープシーケンスを開始します。このシーケンスでは、バックスラッシュと後続の文字の組み合わせが特別なバイト値を表します。

(これは、生でないPython文字列リテラルのエスケープ規則でもあります)。

OPのエラーは明らかにそれとは何の関係もありません。PostgreSQLの優れたドキュメントを研究するという優れたアイデアに加えて、この場合、彼はその形式について心配する必要はありませんE'...';-)。

于 2010-08-01T15:39:11.777 に答える
8

E だけでなく、引用符はユーザーと pw のタイプに関係なく表示されます。%s は単純に str() と同じことを行いますが、これは repr() にフォールバックする可能性があり、どちらにも対応するメソッド__str____repr__. また、それは結果を生成するコードではありません (% があると想定していましたが、現在はコンマしか表示されません)。実際のコード、タイプ、値で質問を拡大してください。

補遺: SQL のように見えることを考えると、データベース インターフェイス モジュールまたはライブラリによって適切に生成されたエスケープ文字列定数が表示されていると推測できます。

于 2010-08-01T13:48:29.263 に答える
2

次のようなことを試みる前に:

statement = "CREATE USER %s PASSWORD %s" % (user, pw)

必ずお読みください:http://www.initd.org/psycopg/docs/usage.html

基本的に問題は、ユーザー入力を受け入れている場合(誰かがユーザーとpwを入力していると思います)、SQLインジェクションを受け入れる可能性が高いということです。

PsyCopg2が述べているように:

Warning Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint.

確認されているように、Postgres(またはPsycopg2)は、識別子をエスケープするための良い答えを提供していないようです。私の意見では、これを解決する最善の方法は、「ホワイトリスト」フィルタリング方法を提供することです。

つまり、「user」と「pw」で許可されている文字を特定します。(おそらくA-Za-z0-9_)。エスケープ文字('または;など)を含めないように注意してください。含めた場合は、これらの値をエスケープしてください。

于 2011-06-01T16:22:34.467 に答える