Viac

Vyhýbajte sa vstrekovaniu SQL pri aktualizácii tabuliek prostredníctvom rozhrania CartoDB API


Snažím sa napísať rutinu, ktorá synchronizuje údaje v našej databáze s databázou CartoDB, aby sme ich mohli zobraziť na mape. Sú to jednoduché veci, ako sú mená a kontaktné údaje, ktoré naši používatelia majú možnosť meniť online. Je nepravdepodobné, že to bude problém, ale napriek tomu je rozumné starať sa o vkladanie SQL.

Existuje odporúčaný spôsob, ako to dosiahnuť pomocou rozhrania SQL API? Píšem otázky ako:

https://ouraccount.cartodb.com/api/v2/sql?q=update our_table set surname = 'Smith' where cartodb_id = 5 & api_key = 123456789

Radšej sa nebudem pokúšať dezinfikovať časť „Smith“ sám a nemôžem nájsť žiadnu dokumentáciu, ktorá by hovorila o tom, že API podporuje parametrizáciu. Čo tu ľudia robia?


ÚPRAVA: Moja stará odpoveď sa týkala iba bežného rozhrania CartoDB API, ktoré umožňuje iba prístup na čítanie.

Vo svojej otázke ste neuviedli, ale zdá sa, že sa snažíte, aby klient odoslal požiadavku na aktualizáciu priamo do API. To nie je dobrý nápad. Po uvoľnení vášho kľúča API pre verejnosť môže ktokoľvek zadávať požiadavky pomocou tohto kľúča. Mal by zostať na vašom serveri. Klienti s ním môžu komunikovať pomocou protokolu OAuth v kombinácii s vaším kľúčom. Takže zhrnutie:

NEgenerujte na strane klienta zápis SQL (INSERT, UPDATE, DELETE). Všetko, čo vyžaduje kľúč API, by sa malo na vašom serveri robiť prostredníctvom interaktivity OAuth. Akýkoľvek prístup na čítanie bez potreby kľúča je v poriadku.

Účelom SQL API s kľúčom je povoliť vašu serverovú aplikáciu, nie klient, na spúšťanie aktualizačných dotazov na CartoDB. Má niekoľko základných kontrol na overenie, či odovzdávate dobrý jazyk SQL, ale parametre za vás nebude parametrizovať.

Nechcel by som sa sám pokúsiť dezinfikovať časť „Smith“

Bohužiaľ budete musieť. Časť rozhrania SQL API, ktorá aktualizuje tabuľky, v súčasnosti vyhľadáva niektoré základné neplatné dotazy, ale nie je navrhnutá na to, aby s ňou klient priamo komunikoval. Musíte zhromaždiť parametre dotazu od používateľa, zodpovedajúcim spôsobom uniknúť a nechať rozhranie svojej aplikácie so samotným API.

Existuje odporúčaný spôsob, ako to dosiahnuť pomocou rozhrania SQL API? Píšem otázky ako:

V tomto odkaze CartoDB načrtáva doteraz nevyvinutú metódu pre budovanie „Named Queries“ na interakciu s API. Aj keď jeho použitie nebolo v čase tohto príspevku implementované v rámci API, poskytuje dobrý prehľad o tom, ako môžete vytvoriť parametrizovaný dotaz na zápis na vašom serveri:

Šablóny dotazov odkazujú na parametre pomocou oddeľovačov <% = a%>. K dispozícii by boli systémové parametre (poskytované serverom, napríklad adresa IP klienta alebo podobné údaje) a používateľské parametre (poskytované používateľom v čase vyvolania).

Aby sa zabránilo vstrekovaniu SQL, bude každý parameter daného „typu“, ktorý určuje požadovaný únik. Podporované typy sú:

sql_literal (interné jednoduché úvodzovky budú uniknuté z sql) sql_ident (interné dvojité úvodzovky budú uniknuté sql) počet (môže obsahovať iba číselné vyjadrenie) ... (podľa potreby doplňte viac) Platné názvy užívateľských parametrov začínajú písmenom obsahovať iba písmená, číslice alebo podčiarkovníky. Názvy systémových parametrov majú predponu sys ::, aby nedošlo k stretu s užívateľskými parametrami.

Užívateľské parametre musia byť explicitne definované v čase vytvorenia NamedQuery s ich predvolenými hodnotami (na kontrolu platnosti SQL).

// namedquery.json {verzia: '0.0.1', // pre každého používateľa môže existovať najviac 1 šablóna s rovnakým menom // platné názvy začínajú písmenom a obsahujú iba písmeno, čísla // alebo podčiarkovníky: 'query_name', // embedded autorizačný certifikát auth: {// Pozri https://github.com/CartoDB/Windshaft-cartodb/wiki/Signed-maps metóda: 'token', // alebo "otvorený" valid_tokens: [' auth_token1 ',' auth_token2 '] // iba pre metódu „token“} // Premenné, ktoré tu nie sú uvedené, nie sú nahradené // Premenná, ktorá nie je poskytnutá v čase spustenia, spôsobí chybu // Pre voliteľné premenné sa vyžaduje predvolená hodnota // Špecifikácia typu sa používa na citovanie, aby sa zabránilo injekciám zástupné symboly: {x: {type: 'number', predvolené: 0}, y: {type: 'number', predvolené: 0}, z: {type: 'number', predvolené: 0}, iso2: {typ: 'sql_literal', predvolené: 'ES'}}, sql: "select CDB_TorqueTile (" + "$$ SELECT * Z krajín, KDE iso2 = '<% = iso2%>' $$," + "<% = z%>, <% = x%>, <% = y%>)", ovplyvnené_tabuľky: 'krajiny' // voliteľné}

Pre ďalšie čítanie pozri tiež túto otázku.


Môže existovať lepší zdroj ako tento blogový príspevok CartoDB, ale teraz môžete vytvárať funkcie sql / plpgsql, ktoré majú veľmi obmedzené použitie a ktoré potom môžete verejne vystaviť, napr .:

VYTVORIŤ ALEBO VYMENIŤ FUNKCIU name_change (_prijimanie TEXT, _id INT) NÁVRATIE celého čísla AS $$ ZAČNITE VYKONAŤ 'AKTUALIZOVAŤ našu tabuľku SET priezvisko = $ 1 KDE cartodb_id = $ 2' POUŽITIE (_prijatie, _id); NÁVRAT 1; KONIEC; $$ JAZYK plpgsql BEZPEČNOSTNÝ DEFINÉR; --Grant prístup k verejnému používateľovi GRANT VYKONAŤ NA FUNKCIU name_change (text, int) TO publicuser;

A potom k tomu získať prístup napríklad:

https://ouraccount.cartodb.com/api/v2/sql?q=SELECT name_change ('Smith', 5)


Pozri si video: Spring Framework. Урок 26: SQL инъекции. PreparedStatement. JDBC API. (Október 2021).