2010-08-01 15 views
15

ten ciąg:pyton dodaje "E" ciąg

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

zawsze zostanie rozszerzony do:

CREATE USER E'someuser' PASSWORD E'somepassword' 

Czy ktoś może mi powiedzieć dlaczego?

Edytuj: Rozszerzony ciąg powyżej jest ciągiem, który moja baza danych przekazuje mi ponownie w komunikacie o błędzie. Używam psycopg2, aby uzyskać dostęp do mojej bazy danych PostgreSQL. Rzeczywisty kod wygląda następująco:

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() 
+7

możesz dać pełny kod z użytkownikiem i pw deklaracje? –

+4

Przyczyną tego może być zachowanie funkcji '__str__' typu' user' i 'pw'. – Philipp

+1

Czy to jest * przecinek * po literale literowym? Jeśli tak, wyrażenie jest po prostu zagnieżdżoną krotką i nic nigdy nie zostanie rozwinięte. Proszę pokazać prawdziwy kod. – Philipp

Odpowiedz

8

Wydaje się, że nie tylko E, ale także cytaty pochodzą od użytkownika i rodzaju pw. % s po prostu robi to, co robi str(), które może wrócić do repr(), z których oba mają odpowiednie metody: __str__ i __repr__. Co więcej, nie jest to kod, który generuje twój wynik (założyłem, że jest%, ale teraz widzę tylko przecinek). Rozwiąż pytanie, podając rzeczywisty kod, typy i wartości.

Dodatek: Biorąc pod uwagę, że wygląda na SQL, mogę zaryzykować przypuszczenie, że widzisz escape string constants, prawdopodobnie wygenerowany poprawnie przez moduł interfejsu bazy danych lub bibliotekę.

+0

Masz rację. Używam Psycopg2 i jest to ciąg, który moja baza danych zwróciła mi jako błąd. Zamierzam teraz umieścić aktualny kod w pytaniu. – Kai

+0

Wygląda na to, że problem jest związany z% s dla pól danych, a nazwa użytkownika w [CREATE USER] (http://www.postgresql.org/docs/8.2/interactive/sql-createrole.html) wydaje się być identyfikator - więc literał łańcuchowy nie będzie tam działać. Wydaje się, że Psycopg2 nie ma żadnych funkcji sprawdzania poprawności ani cytowania dla takich identyfikatorów. –

+1

[Odpowiednia dyskusja psycopg.] (Http://lists.initd.org/pipermail/psycopg/2009-March/thread.html#6344) –

10

Jak edytować PO ujawnia on używa PostgreSQL, the docs za to są istotne, a oni mówią:

PostgreSQL akceptuje również „uciec” stałe ciągów znaków, które stanowią rozszerzenie standardu SQL. Stała ciągowa ciągu znaków jest określona przez , pisząc literę E (górny lub dolny przypadek ) tuż przed otwarciem pojedynczego cytatu , np. E'foo ".

Innymi słowy, psycopg jest prawidłowo generowania ewakuacyjnych stałe ciągów znaków dla swoich strun (tak, jak docs powiedzieć też:

ciągu ciąg ucieczki, backsleshem postać() rozpoczyna C -jak sekwencja ucieczki ukośnikowe, w którym kombinacji ukośnikiem i po znaku (ów), oznacza szczególną wartość bajtu.

(które jak się okazało są także konwencjami escape liter nieciągłych liter Pythona).

Błąd OP najwyraźniej nie ma z tym nic wspólnego, a poza doskonałym pomysłem na studiowanie doskonałych dokumentów PostgreSQL, nie powinien się w tym przypadku martwić o ten formularz ;-).

+1

Po prostu przeczytaj to sam. Więc ciąg jest poprawny, ale dlaczego mój serwer Postgresu zwraca mi go z błędem składni w E? – Kai

+0

@Kai, może używasz przestarzałej wersji PgSQL? A może komentarze @ Yanna dotyczące drugiej odpowiedzi są poprawne i potrzebujesz identyfikatora, _nie_ cytowanego ciągu w ogóle, w 'CREATE USER' (w takim przypadku będziesz musiał wstawić go przez manipulację ciągami, przed' execute', aby uniknąć ucieczki - koniecznie ** sprawdź ** bardzo dokładnie przeciwko atakom typu SQL injection !!! -). –

+0

Wygląda na to, że komentarz Yanna ma rację. Nie podoba mi się to, ale w tej chwili nie potrzebuję obsługiwać wartości generowanych przez użytkownika w tych instrukcjach. Więc po prostu użyję standardowych manipulacji ciągiem Pythona. Nadal nie podoba mi się;) – Kai

2

Przed przystąpieniem coś takiego:

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

Upewnij czytasz: http://www.initd.org/psycopg/docs/usage.html

Zasadniczo chodzi o to, że jeśli przyjmujemy dane wejściowe użytkownika (zakładam więc jak ktoś wkracza w użytkownikowi & pw) prawdopodobnie pozostawisz otwartą na iniekcję SQL.

Jak psycopg2 stwierdza:

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

Jak zostało zidentyfikowane, PostgreSQL (lub psycopg2) nie wydaje się, aby zapewnić dobrą odpowiedź do identyfikatorów uciekających. Moim zdaniem najlepszym sposobem rozwiązania tego problemu jest zapewnienie "białej" metody filtrowania.

tj .: Określ, jakie znaki są dozwolone w "użytkowniku" i "pw". (być może A-Za-z0-9_). Uważaj, aby nie wstawiać znaków ewakuacyjnych ("lub;, itp.), A jeśli tak, to unikać tych wartości.

+0

Postgres ma funkcję 'quote_ident()' do cytowania identyfikatorów https://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-QUOTE-LITERAL -EXAMPLE – raphael

16

Aby przejść identyfikatory do PostgreSQL przez psycopg użytku AsIs z modułu

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' 

extensions który działa również na przejściu warunków klauzul jak 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' 
+0

Szkoda, że ​​pokonuje punkt parametryzacji zapytania: '>>> cursor.mogrify ('CREATE USER% s PASSWORD% s', (ASIs ('someuser'), Asi ('somassword; drop table users ; '))) ' '' CREATE USER someuser HASŁO użytkownicy tabel upuszczania; '' Powinno to zostać zatwierdzone za pomocą czegoś takiego: ''input_table'.replace (' _ ',' ') .isalnum()'. (Uwaga, nie testowano.) –

+0

@ MichałPawłowski: Tak, "Asi" nie powinno być używane dla danych wprowadzonych przez użytkownika. I używanie każdego niezupełnie przetestowanego rozwiązania, jak to robisz, jest receptą na katastrofę. –