spájame
slovenskú
IT komunitu
pridaj sa
Registrácia · Login

František Čaník 29.1.2013
Hodnoť článok:
0 0

Quick tip: Maintenance s umožneným vstupom

Často krát potrebujete vypnúť stránku kôli nejakej údržbe, alebo len kôli pretestovaniu novej funkcionality, ktorú ste dorobili a tak zapnete (ak sa bavíme o Nette) iba require na súbor .maintenance.php. Ako na to elegantne? Požadovaný NETTE LEVEL: Mierne pokročilý.

Vezmime si príklad, kedy potrebujete nahodiť niekam nový web, ale ešte nechcete, aby fungoval verejne. Môžete ho ukazovať na vlastnom serveri, alebo na nejakej subdoméne, avšak tak či onak potrebujete na produkčnom prostredí testovať, či všetko beží tak ako má. A tu prichádza otázka, ako na to a hlavne čo najelegantnejšie?

Maintenance s prístupom pre určité skupiny?

Bežný maintenance súbor zablokuje celkovo celý prístup s informáciou o tom, že na stránke prebieha údržba. Na tom by nebolo nič zlé, keby nebolo treba povoliť aspoň niekoho. Tu teda prichádza otázka, ako toho niekoho identifikovať? Najlepšie asi cez IP adresu, z ktorej pristupuje, nie? Takže si vezmeme náš BasePresenter a pozrieme sa, ako funguje a čo robí.

Dôležitá funkcia startup

Pozrite sa, či Váš BasePresenter obsahuje funkciu startup. Ak nie, vytvorte ju a do nej si vložíme overovanie, ktoré nám bude rozhodovať o tom, čo návštevník uvidí.

// zistíme si IP adresu používateľa
$currentIP = $this->httpRequest->getRemoteAddress();

// vytvoríme si pole s prístupmi
$allowed = $db->fetchAll('SELECT allowed_ip FROM allowed_hosts WHERE allowed_from < ? && allowed_to > ?',time(),time());

// ako vidíte, podmienka sleduje, či má používateľ ešte platné povolenie, ktoré sa nastaví na základe zadania správneho hesla

// prejdeme si pole s povolenými používateľmi
foreach($allowed as $ip) {
      $allow[] = $ip->allowed_ip;
}

// z config.neon si vyberieme heslo
$unlock = $this->context->parameters['site']['unlockPass'];

// overíme si, či aktuálna IP je v zozname povolených

if(!in_array($currentIP,$allow)) {
    if($_POST['UnlockPassword'] != '' && $_POST['UnlockPassword'] == $unlock) {
        $in = $db->table('allowed_hosts')->insert(
             array('allowed_ip' => $currentIP,
                   'allowed_from' => time(),
                   'allowed_to' => strtotime('+24 hours')
                   )
        );
        if($in) {
            $this->flashMessage($this->translator->translate('Vaša IP adresa bola pridaná medzi povolené. Toto povolenie vyprší za 24 hodín').' - '.date("d.m.Y, H:i",strtotime('+24 hours')),'success');

            $this->redirect('Homepage:index');
        }
     }
     $this->setLayout('maintenance');
}

Čo obsahuje táto časť kódu?

Ako ste si všimli, vyberáme v úvode IPčky z databázy, ktorá obsahuje polia ako allowed_ip, allowed_from a allowed_to. Prvý parameter asi netreba vysvetlovať. Druhý a tretí sú v podstate timestamp-y, ktoré označujú obdobie 24 hodín. Toto je samozrejme niečo, čo si môžete zmeniť.

Ďalej kód získava aktuálnu IP adresu z httpRequest-u. Pre istotu odporúčam pridať na začiatok triedy injektor, ktorý sa postará o to, že budete môcť $this->httpRequest volať kdekoľvek:

private $httpRequest;

public function injectHttpRequest(Nette\Http\IRequest $httpRequest)
{
    $this->httpRequest = $httpRequest;
}

Po vytvorení pola s IP adresami a porovnaním s aktuálnou sa script dostáva na podmienku, ktorá zisťuje, či bolo odoslané heslo. Teda, aspoň v prípade, že sa Vaša IP adresa nenachádza medzi povolenými IPčkami.

Pri zistení "POST" requestu sa overuje zhoda s heslom, ktoré je zadefinované v config.neon. Samozrejme aj toto si môžete ľubovoľne meniť. Je to len a len na Vás. Config.neon našťastie spadá pod adresáre, kde nie je (htaccessom) povolený prístup, takže by mal byť teoreticky ochránený.

Ak nespĺňate podmienku, nič sa nedeje, stále sa Vám nastavuje layout pre maintenance $this->setLayout('maintenance') v ktorom máte jednoduchý formulár a info o tom, že na stránkach sa pracuje a ak máte heslo, môžete si ich zobraziť. Kreativite sa medze predsa nekladú nie? Takže opäť je to na Vás, ako bude vyzerať.

Ak podmienky splníte, Vaša IP adresa sa zapíše do databázy na 24 hodín a tým pádom sa už nedostanete na podmienku, ktorá prikazuje layout pre maintenance.

Záverom

Ak by sa niekto pýtal, prečo som písal tento článok, alebo že to nie je nič nové... Písal som ho práve preto, že viem, že ľudia sú radi, keď si vedia uľahčiť prácu a ak im to pomôže ochrániť si tak (aspoň dočasne) webku a umožniť klientom browsovať aj cez devel mód, tak je to len a len fajn. Či?

P.S.:
Ak by niekto predsa len chcel a potreboval:

DROP TABLE IF EXISTS `allowed_hosts`;
CREATE TABLE `allowed_hosts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `allowed_ip` varchar(39) DEFAULT NULL,
  `allowed_from` timestamp NULL DEFAULT NULL,
  `allowed_to` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
František Čaník František Čaník

Programátor, webdesigner a webdeveloper niekoľkých webových projektov. Má za sebou prácu v reklamnej agentúre, médiách a na rôznych pozíciách v oblasti IT.


Hodnoť článok:
0 0

22 komentárov k článku:

Komentovať môžu iba prihlásení

Zaregistruj sa cez bezplatnú registráciu alebo použi login cez Facebook (FB Connect)

Prihlás sa tu, ak už máš profil na Zajtra.sk:


Zabudol som heslo

0 0 Miloš 19.2.2013 12:38:59
František: To znie už lepšie.
0 0 František Čaník 19.2.2013 01:17:57
@Miloš v jednej verzii CMSka som využil, že sa IP adresy ukladali na 24 hodín a aj to po zadaní správneho hesla. Takže ak si poznal heslo, systém ti automaticky povolil aktuálnu IP. Samozrejme to bolo rozšírené o pevne určené IP adresy, ktoré mali prístup okamžite a nemuseli zadávať heslo. Poväčšinou je to vecou ISP ako ti prideľuje IP adresy a vecou nastavení, ako dlho budeš danú IP storovať ako povolenú. Takže si myslím, že veľmi jednoduché a čisté. ;) (teda, aspoň čo sa týka toho riešenia čo popisujem v komente).
0 0 Miloš 18.2.2013 23:37:53
Kontrola cez IP je chyba, riešil by som to cez meno a heslo. Prečo? Pretože cez mobil mám dynamickú IP. Telekom prideľuje tiež dynamické IP pre DSL. Pokiaľ by to niekto potreboval vo firme v rámci vlastnej siete, tak sa to ešte dá pochopiť, ale toto je zrejme o verejne prístupnej stránke. A navyše načo zisťovať niekoho IP, keď vieme jeho meno a heslo (teda, aby som bol presný, tak heslo nevieme, ale vieme overiť prihlásenie cez meno a heslo). Ale možno v tvojom prípade sa jedná o niečo špecifické a tam je IP výhodnejšia, takže neber môj názor tak, že sa ti ho snažím vnútiť.
0 0 Ján Chorvát 31.1.2013 16:35:06
@František Čaník Je to tak, ako pisal @Ucitel. Tie chyby v databazovej strukture boli uplne zakladne. A ak si to cita niekto neskuseny, tak by mohol ziskat dojem, ze je to v poriadku.

Indexy mozes nastavovat neskor, pocas optimalizacie, ale spravne nastavenie datovych typov je zaklad. Cudzie kluce su vacsinou tiez jasne hned.

Len na okraj, to prechadzanie povolenych ip cez foreach si si mohol usetrit, ak by si ich z db vybral pomocou metody $db->query("...")->fetchPairs(NULL, 'allowed_ip'). Rovno by sa ti vytvorilo pole len s ip adresami.
0 0 Ucitel 31.1.2013 16:11:07
@Lukáš Staňa Tnx za tip, nevedel som ze priamo v PHP je funkcia na prevod adresy do tohto formatu.

@František Čaník Clovek by nemal riesit veci, kde nema stopercentnu strukturu, potom velmi rychlo vznika bordel. Ja osobne robim navrh databazy ako jeden z prvych krokov pri vyvoji aplikacie, potom mas model ktory zachytava vacsinu objektov v aplikacii a vztahy medzi nimi, ktory mozes vyuzit pri vyvoji samotnej aplikacnej logiky.

Vyklikat rychlo nieco v Admineri, nakodit aplikaciu a nakoniec pomenit datove typy, nahadzat nejake cudzie kluce a volat to optimalizacia urcite nie je dobry pristup.
0 0 František Čaník 31.1.2013 14:18:34
Neboj, neberiem. Len to pre takéto prípady nepovažujem za podstatné. Mimo to, keď človek rieši veci, kde ešte nemá stopercentnú štruktúru, tak optimalizácie týchto vecí sú vždy až jedným z posledných krokov, rovnako ako nastavovanie závislostí, indexov, cudzích kľúčov a pod. Ale to sa len málokedy (ak vôbec) chápe.
3 0 Lukáš Staňa 31.1.2013 10:49:35
@František Čaník :) Super :) Neber to tak katastroficky. Písanie článkov predsa nie je o tom že ja som mega cool brutal expert v tom, o čom píšem a všetci mi máte v komentároch ďakovať a velebiť. Ak predsa niekto suggestne nejaké vylepšenie, odúlenie sa a flamewar nie je na mieste a radšej tento suggest zapracovať aj pre niekoho, kto sa prekliká na daný článok neskôr a takto nepriamo pozdvihnúť kvalitu slovenského programovania. Som idealista, čo už. Mier s vami ;)
0 0 František Čaník 31.1.2013 00:51:51
Lukas: maximalny suhlas aj co sa tyka datovych typov pre mysql. co sa tyka urcenia typov, ked pises clanok v rychlosti, kym ho mas v hlave a nepremyslas nad tym, tak das proste najcastejsi datovy typ a neriesis. Pre vsetkych som to upravil podla najlepsich napadov a snad uz budete mat vsetci srdiecka na miestach.
3 0 Lukáš Staňa 31.1.2013 00:11:34
Fajn návod, takto by mi to nenapadlo riešiť.
K samotnému flamewaru:
- Na unixtimestampoidné dáta máme predsa v MySQL dátový typ TIMESTAMP, ten si interne ukladá dáta ako unix timestamp integer.
- IPv6 sú dnes už samozrejmejšie ako si myslíme, no len si skús očami prejsť access log nejakého frekventovanejšieho webu (teda, ak tvoj hoster je IPv6 ready). Zákazníkom takisto priradzujeme IPv6 adresu (pracujem pre lokál ISP)
- Ak už ukladať IPv4 adresu tak ako INTEGER a použiť kamarátov INET_ATON/INET_NTOA, prípadne PHP ekvivalenty long2ip/ip2long (pozor, pri starších verziách PHP to treba ešte obaliť sprintf-om)
- Toto je skôr moj osobný názor, takže nebrať vzťahovačne. Ale keď developer už napíše takýto quickie SQL a priordzene nerozmýšľa nad dátovými typmi, neviem si predstaviť serióznejšie dátové štruktúry. Ale to je len môj skromný postreh šitý na moje zmýšľanie.
0 0 Ján Chorvát 30.1.2013 10:42:18
Videl som už všeličo, ale ukladať integer (čo unix timestamp je) ako reťazec, to je tak zlé, až sa mi chce plakať...
0 0 Ucitel 29.1.2013 17:39:00
@František Čaník Nie, DATETIME sa pouziva na casove udaje vseobecne, ak mas data vo forme unix timestampu mozes pouzit napr. FROM_UNIXTIME() funkciu v MySQL resp. ekvivalent pre ine DB alebo to naformatovat spravne na strane PHP - date('c').
Co sa tyka IP, ano 39 je najvacsia dlzka beznej IPv6 adresy.
Viem ze su to detaily, len nechcem aby si niekto z clanku odniesol, ze data v databaze ukladame do VARCHARov s nahodnou dlzkou.
0 0 František Čaník 29.1.2013 17:14:26
Ucitel: A) na unix timestamp pouzit DATE TIME? hmm, if u think, try. B) 39 znakov na IP? Predpokladas ze uz ti niekto vrati IPV6? C) Tak ci onak, nejde a ani mi neslo o napisanie optimalizovaneho mysql kodu, pretoze realne, pouzivanie niecoho takehoto je otazkou kolko? tyzdna? kym bude web spusteny a kym sa len "pod heslom" testuje? Takze sa nebavime o 100000 IP adries a o indexovanych poliach a teda dlzky a typy datovych poli su irelevantne.
2 0 Ucitel 29.1.2013 17:06:28
V SQL sa na ukladanie casovych zaznamov pouziva typ DATETIME resp. DATE, pouzivanie VARCHARov s nahodnou dlzkou nie je ziaden extra dobry napad. Na IP adresu ti tiez staci VARCHAR(39).
0 1 Nikto 29.1.2013 16:06:37
Mozes to spravit zlozitejsou cestou tak, ze napises aj nejake php a to potom rozhoduje o vsetkom na zaklade toho suboru alebo jednoducho ho redirectnes priamo cez ten subor.
Je to uplne jedno hadame sa tu o somarinach ktore nikoho nezaujimaju a stale sa tocime okolo jednej veci dookola. Vzdy to bolo a vzdy to bude lepsie riesit cez php (ci uz cestou ako ides ty alebo inou) ale ako som uz pisal pride mi to pre moje potreby zbytocne a preto mi bohato postaci spravit si behom par sekund "alternativu".
0 0 František Čaník 29.1.2013 15:50:43
Nikto: daj nejaky priklad stranky, kde mas landing page so zakladnym layoutom webu a cez htaccess umoznis cloveku co zada heslo {len heslo} aby videl cely web. Fakt hlboko o tom pochybujem, ze najdes.
0 1 Nikto 29.1.2013 15:26:32
Tak tak ved to hovorim odzaciatku, kazdy nech pouziva to co mu vyhovuje. Je na to velmi vela sposobov v com podla mna spociva krasa pisania kodu.
Netvrdim, ze je to zlozite riesenie ale hovorim to v porovnai s htaccess ktore nevyzaduje db a jeho tvorba je rychlejsia.
0 0 František Čaník 29.1.2013 14:48:47
Každý má svoje vlastné spôsoby. Ak máš rád ten svoj, používaj ho. Je to tvoja voľba predsa nie? AK ti toto príde ako "robustné" (na pár riadkoch kódu), (s čím vie pracovať viac programátorov) tak potom fakt neviem... Nik ti to neberie.
0 1 Nikto 29.1.2013 14:41:02
Tak s tym sa daju robit vseliake veci kludne aj redirect. Pripadne by som mohol includnut nejaky list na indexe na zaklade nejakej podmienky. Ako som pisal da sa to spravit na vela sposobov a da sa to aj poriadne prespekulovat a to co som spomenul ja alebo ty je len cast moznosti.
Premna je v podstate klucovy fakt, ze cez htaccess to spravim do 20 sekund aj s vytvaranim suboru. Nemam nic proti robustnejsiemu rieseniu ale zatial mi to priapda ako overkill pre moje potreby.
0 0 František Čaník 29.1.2013 14:19:32
Nikto: Ako budeš stvojím htaccessom riešiť landing page pre bežných užívateľov? Nijak, že? Tak ti neviem... Každý ako mu je lepšie.
0 1 Nikto 29.1.2013 14:10:29
Viem ako funguje htaccess na pass pripadne blokovanie/povolovanie na zaklade ip adresy cez tento subor a podobne len ma zaujimalo preco si to tak neriesil. Toto je vec ktora sa da robit strasne vela sposobmi zatial ostavam po starom, dik za info.
Zajtra.sk > Programovanie > PHP > Quick tip: Maintenance s umožneným vstupom


Kritika

Vieš ako robiť veci lepšie? Pomôž našim odvážnejším členom a skritizuj im projekty!

Reklama

Seriály zo Zajtra.sk

Reklama