Přejít k navigační liště

Zdroják » Databáze » Amazon SimpleDB prakticky v PHP

Amazon SimpleDB prakticky v PHP

Články Databáze

V předchozím článku o Amazon SimpleDB jsme si popsali principy funkce této databáze. Dnes si ukážeme, jak s touto databází pracovat přímo na úrovni API. Amazon SimpleDB nabízí pro přístup k službám rozhraní SOAP a REST. V článku si ukážeme, jak využít to druhé, a to z prostředí jazyka PHP.

Velké webové služby většinou nabízejí vlastní knihovny pro nejpoužívanější jazyky. Ani v případě Amazon SimpleDB tomu není jinak – k dispozici jsou knihovny pro PHP, Javu, Perl, C# a VB.NET. Ačkoli nejsem obecně příznivcem znovuvynalézání kola a řídím se heslem, že je lépe použít vyhovující knihovnu než opakovat stejné chyby jako její autoři, v případě SimpleDB a PHP jsem na vážkách – PHP knihovna nabízená Amazonem mi připadá poněkud těžkopádná. Sice je dobře dokumentovaná a testovatelná, ale osobně mi připadá poměrně nešikovně uspořádaná (jde spíš o otázku preferencí než o rozhodnutelný fakt).

Ať tak či onak, faktem je, že na webu lze nalézt spousty knihoven třetích stran, jejichž autorům zjevně kód od Amazonu nevyhovoval, takže se rozhodli udělat vlastní knihovny, které sahají od jednosouborových wrapperů po komplexní knihovny pro celé Amazon AWS. Jako kuriozitu bych zmínil Super SimpleDB, což je knihovna, která nad SimpleDB simuluje SQL dotazy.

Naštěstí je „REST“ rozhraní SimpleDB bohatě dokumentované, takže není problém s ním pracovat – vystačíme si v zásadě se základní schopností „poslat HTTP GET požadavek“ a s hashovacími funkcemi. V tomto článku si ukážeme, jak vytvořit požadavek na SimpleDB, jak ho podepsat a jak jej poslat.

Poznámka: Amazon své rozhraní nazývá „REST“, ačkoli očividně nesplňuje základní znaky tohoto architektonického stylu – např. pro všechny požadavky, včetně těch co mění data, používá HTTP GET (pro zajímavost – o POSTu se zmiňuje dev guide takto: „If the length of the query string that you are constructing exceeds the maximum length of the HTTP GET URL, use HTTP POST and submit the query string parameters in the body of the message“), přístup není orientovaný na záznamy, ale na procedury atd. Ve skutečnosti jde spíš o „RPC over HTTP“. V dalším textu se ale přidržím terminologie Amazonu a budu toto rozhraní označovat, kvůli zachování konzistence s dokumentací, jako „REST“. Zájemce o podrobnější vysvětlení problematiky RESTu a rozdílu proti RPC odkážu na komentáře Petera Rybára.

Autentizace SimpleDB

SimpleDB používá pro přístup ke službám stejné údaje jako ostatní AWS služby – tedy unikátní dvojici řetězců Access Key a Secret Key. Access Key je posílán spolu s požadavkem jako identifikátor konkrétního uživatele, Secret Key je použit k výpočtu „podpisu“ pro konkrétní požadavek, a to pomocí HMAC-SHA256 algoritmu.

Autentizace požadavku je poměrně jednoduchá, spočívá ve třech krocích:

  1. Příprava požadavku
  2. Výpočet HMAC-SHA256 hashe, kdy je použit Secret Key coby klíč
  3. Přidání spočítaného hashe k požadavku

Příprava požadavku je pravděpodobně nejnáročnější částí. Pojďme si ji probrat podrobněji.

Příprava požadavku

Požadavek se skládá z parametrů ve tvaru „název=hodnota“. Nejprve jsou parametry seřazeny podle názvu abecedně ve vzestupném pořadí. Následně jsou spojeny pomocí ampersandu, stejně jako v query u HTTP požadavků, a stejně jako u HTTP jsou i zde hodnoty enkódovány, s drobnými rozdíly – např. mezera není kódována jako „+“, ale jako „%20“. V PHP můžeme použít funkci rawurlencode.

Příklad: AWSAccessKeyId=0123456789ABCDEF
&Action=Select
&DomainName=MyDomain
&SelectExpression=select%20%2A%20from%20MyDomain%20where%20Ite%20%3E%20%270100.00%27
&SignatureMethod=HmacSHA256
&SignatureVersion=2
&Timestamp=2010-04-14T17%3A08%3A12%2B00%3A00
&Version=2009-04-15

Požadavek se skládá z některých povinných parametrů (AWSAccessKeyId – viz výše zmíněný Access Key, Action – název akce, viz předchozí článek, Domain Name – jméno domény, SignatureMethod, SignatureVersion, Version a Timestamp), z parametrů specifických pro daný požadavek (SelectExpression) a z nepovinných parametrů (zde není použit žádný, ale lze specifikovat např. počet vrácených záznamů).

Máme-li požadavek takto normalizován (parametry seřazeny podle abecedy, hodnoty ošetřeny), vytvoříme si řetězec k podpisu:

HTTPVerb + "n" +
Host + "n" +
RequestURI + "n" +
QueryString

HTTPVerb je použitá metoda (GET nebo POST), Host je plné jméno serveru malými písmeny (většinou „sdb.amazonaw­s.com“), RequestURI je v této verzi API vždy „/“, a QueryString je výše popsaný řetězec s požadavkem. Pro takto vytvořený řetězec spočítáme HMAC-SHA256 hash, kde jako klíč použijeme náš Secret Key, a výsledek přidáme k požadavku jako parametr Signature.

Podepsání požadavku

K výpočtu použijeme v PHP funkci hash_hmac s výstupem jako raw:

$signature = hash_hmac ( 'SHA256', "GETnsdb.amazonaws.comn/n" . $request , 'SECRET KEY', true );

Binární výstup funkce hash_hmac zakódujeme pomocí base64_encode a výsledek před vložením do požadavku ošetříme pomocí rawurlencode. S podepsaným požadavkem pak zavoláme HTTPS GET – buď přes cURL, nebo přes socks, nebo jiným způsobem, podle toho, co náš systém podporuje.

Výsledkem operace je chybové hlášení nebo potvrzení operace. Má vždy formát XML souboru, lze jej tedy snadno parsovat a zpracovat.

Praktická ukázka v PHP

Ukažme si, jak lze pracovat se SimpleDB přímo, bez použití knihovny. V ukázce se zaměříme na algoritmus podepisování a na volání API – nebudeme tedy ošetřovat chyby, timeout u HTTP požadavku, ani nebudeme zpracovávat výsledek.

Nejprve si připravíme data pro požadavek, klidně jako asociativní pole:

$query = array(
'Action'=>'PutAttributes',
'DomainName'=>'MyDomain',
'ItemName'=>'Svetr123',
'Attribute.1.Name'=>'Color','Attribute.1.Value'=>'Blue',
'Attribute.2.Name'=>'Size','Attribute.2.Value'=>'XXL',
'Attribute.3.Name'=>'Price','Attribute.3.Value'=>'000024.99');

Je vidět, že voláme akci PutAttributes, budeme ji vykonávat v doméně MyDomain, jméno položky (klíč) bude Svetr123, a budou jí přiřazeny tři atributy – Color, Size a Price. Jistě vás nepřekvapí, že cena je zleva doplněna nulami – v minulém článku jsme si říkali, že SimpleDB zachází s čísly jako s řetězci, a pokud je chceme porovnávat, musíme je normalizovat.

Všechny hodnoty proženeme přes funkci rawurlencode – lze použít array_filter. V tomto příkladu nejsou použity žádné znaky, které by bylo nutné ošetřovat, výsledek by měl být tedy stejný.

K parametrům přidáme povinné údaje:

$query['Version']='2009-04-15'; //vždy
$query['Timestamp']= urlencode(date('c'));
$query['SignatureVersion']='2'; //vždy
$query['SignatureMethod']='HmacSHA256'; //vždy
$query['AWSAccessKeyId']='0123456789ABCDEF';

Vy samosebou použijete vlastní Access Key.Version, SignatureVersion a SignatureMethod mají v současné verzi API výše uvedené hodnoty.

Při testech jsem měl největší problém se správným formátem Timestamp, nakonec se jako použitelný ukázal urlenkódovaný výstup data a času podle ISO 8601, který vrací funkce date() s řetězcem ‚c‘.

Pokračujeme podepsáním požadavku podle výše zmíněného postupu:

ksort($query); //setřídění podle jména parametru

$request = http_build_query ($query);

$secret = 'bflmpsvzhkrdtn123456zabbfem/asoic-quake987'; //SecretKey

$sign = hash_hmac ( 'SHA256', "GETnsdb.amazonaws.comn/n" . $requesr , $secret, true );

$query = $request . '&Signature=' . urlencode(base64_encode($sign));

Výsledkem je požadavek ($query), doplněný o podpis. Je vidět, že protokol nezaručuje unikátnost požadavku – pokud by požadavek zachytil útočník na trase, může jej teoreticky zopakovat, protože podpis zůstane stejný. AWS umožní provedení operace po dobu 15 minut od času uvedeného v timestamp.

Požadavek stačí už jen odeslat na server https://sdb.a­mazonaws.com/ – lze to udělat pomocí cURL, nebo i pomocí fsockopen – já použil druhou zmíněnou metodu:

$response = '';
$fp = fsockopen("ssl://sdb.amazonaws.com", 443, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)n";
} else {
    $out = "GET /?" . $query . " HTTP/1.1rn";
    $out .= "Host: sdb.amazonaws.comrn";
    $out .= "Connection: Closernrn";
    fwrite($fp, $out);
    while (!feof($fp)) {
        $response .= fgets($fp, 128);
    }
    fclose($fp);
}

Výsledek operace získáme v proměnné response jako XML data.

Závěr

Práce se SimpleDB pomocí REST rozhraní (s výhradou vůči pojmenování REST, viz výše) je opravdu snadná i bez použití knihoven. Jediná možná problematičtější pasáž je podepisování požadavků, ale po podrobnějším pročtení dokumentace (a odhalení správných funkcí pro hash, ošetření hodnot a vygenerování časového razítka) je tento úkol velmi snadný.

Pokud budete zvažovat použití SimpleDB ve své aplikaci, sáhnete pravděpodobně po hotové knihovně, ale pro první pokusy a „osahání“ API na poměrně nízké úrovni lze, jak jsme si ukázali, použít těch nejjednodušších prostředků.

Komentáře

Odebírat
Upozornit na
guest
0 Komentářů
Nejstarší
Nejnovější Nejvíce hlasů

Proč vám model napíše Python, i když jste si řekli o Rust

AI
Komentáře: 0
Výkonnostní propast mezi Pythonem a ostatními jazyky se za poslední rok a půl skoro zavřela. Dnešní modely zvládají Rust i Go srovnatelně dobře. Když jim ale volbu necháte, sáhnou stejně po Pythonu. A u knihoven je to ještě výraznější: mezi funkčně srovnatelnými balíčky je až 84procentní rozdíl v kvalitě generovaného kódu. Proč to tak je a co s tím.

WP2Shell: Kritická hrozba pro samotné jádro WordPressu. Útočníci mohou získat kontrolu nad webem

Zranitelnost ve WordPressu není žádná novinka. Kdo provozuje weby postavené na této platformě, ví, že bezpečnostní záplaty chodí prakticky pořád. O to větší pozornost by měla vzbudit chyba, u které nic z toho neplatí. A přesně takový je případ zranitelnosti, která dostala přezdívku wp2shell. potřeb. Zranitelný kontaktní formulář, děravý e-shopový plugin, opomenutá kontrola oprávnění v nějaké obskurní rozšiřující knihovně – to je denní chleba každého, kdo sleduje bezpečnostní feedy. Zpráva „nová chyba ve WordPress pluginu“ má tak nízkou informační hodnotu, že ji většina lidí přejde bez mrknutí oka.

Mýtus jedné aplikace: proč PWA nenahradí vývoj pro každou platformu

PWA mohou webu přidat ikonu na ploše, fungování bez připojení, notifikace a některé systémové funkce. Nejsou ale cestou k jednomu klientu pro všechny platformy. Vyplatí se tam, kde se lidé k webu vracejí a ocení okamžitý vstup z odkazu. Jakmile aplikace musí spolehlivě běžet na pozadí nebo fungovat stejně na každém zařízení, bývá vhodnější nativní řešení.