Архив на категория: Техническа

Къде да валидираме в MVC модела?

Странно, но последните няколко дни постоянно се сблъсквам с един въпрос „Къде да валидираме“, и постоянно трябва да обяснявам, че валидацията на данните ВИНАГИ, ама наистина ВИНАГИ, става в модела, а не в контролера. За съжаление,  масово  по мрежата примерите се дават с валидация в контролера, и ако хванете нещо като CodeIgniter, най-вероятно ще се подхлъзнете. Причините за тази грешка са две. Едната е, че Сульо и Пульо, къде знаят и не знаят, почнали да дават акъл, лошо няма в това, но  подвежда хората. Втората, по-основната причина е, че така е по-лесно, и в малки проекти изглежда логично, и че не пречи.

Защо обаче трябва да е в модела? За да разберете, отговорите си на въпроса „Какво е модел“. Това е мястото където се държат данните и тяхната логика (най-грубо казано). Кой трябва да се грижи за валидността на данните? Този, който ги държи, и се грижи за тях, или някой друг? представете си, че вие работите, взимате заплата, но някой друг ви харчи парите, без да го е грижа какви са вашите планове. Кофти е, нали? Точно това се случва, когато валидирате в контролера.

Вижте, в малки проекти наистина няма значение, на местата където даден модел се вика 1-2 пъти само и общо взето се получава, че за всеки метод в контролера имате 1-2 метода в модела, и те не се ползват другаде. Обаче при по-големи проекти, особено такива направени с акъла си, един модел се ползва на много места. Тогава какво трябва да направите? Да имате няколко еднакви валидации на тези няколко места? Това е тъпо, определено. А какво ще стане, като започнете да променяте правилата за валидация? Трябва да ги смените на всички места, което отново е тъпо.

Моделът е самостоятелна единица, грижеща се за данните, а може би най-важното нещо, които трябва да направим с данните е да ги валидираме.

Започнахте ли да схващате? Дано, ще си спестите много проблеми в бъдеще.

Искам да направя едно уточнение, в контролера може да има валидация на данните, но само ако в следствие на тази валидация, контролера трябва да изпълни различно действие. Данни, които ще се мениджърът от модела, се валидират САМО от модела. Ааа да, и още едно уточнение, в едно предишно мое видео за MVC бях казал, че валидацията се прави в контролера. Еми, както казах „Сульо и Пульо….“. Определено тогава греших в разбиранията си, и се бях подвел по едни фреймуркове……

Ако си зададете въпроса „Ако сега взема тоя модел, и го сложа в друг проект, ще работи ли както трябва, ще се счупи ли, ще ми се дънят ли данните, без да се налага да пипам други части от системата“ (в контекста на данни) и си отговорите „Да“, значи всичко е наред с модела, и сте го написали правилно. Модела взима данните чрез параметри, параметрите контролират неговото поведение, той не трябва да се интересува кой го вика, къде връща.

Сега идва въпроса, как да връщаме грешките от модела, и има няколко начина. Единият, особено подходящ за езици като Java и C#, е класическия try/catch. Паролата е прекалено къса? просто модела ще си хвърли изключение, и извикващият го обект ще има грижата да се оправя. В тези езици това наистина е удачен начин, понеже изключенията са обекти, и въобще цялата им платформа е изградена върху тези концепции. Обаче в света на PHP, въпреки, че можем да ползваме същата техника, да си създаваме свой Exception класове, и да ги връщаме, не винаги това е най-удачният вариант. Въпрос на вкус, както се казва. Един прост елегантен вариант е следният:

class UserModel{
public function registerUser($username,$pass){
$return[‘success’]=false;
$return[‘errors’]=null;
if(mb_strlen(trim($username)){
$return[‘eroors’][]=“username_too_short“;
}
//други валидации, дали имеето е заето…..
if($return[‘errors’]==null){
//нямам грешка, пише SQL за запис в базата или там каквото трябва да правим
$return[‘success’]=true;

}
return $return;
}
}

И така, нещото което го извиква, винаги получава отговор, и ако success===true, значи е минало, ако е false, значи нещо се е объркало и търси в масива errors какво се е объркало.

Разбира се, това е елементарен пример, само за да покаже концепцията, може да го направите по-мазен, ако искате, но основната идея е, винаги да има отговор, който по подразбиране е false, и само и единствено като сме сигурни, че всичко е минало както трябва връщаме true.

Ами какво става с FormValidation класовете, дето толкова се бутат по тия frameworks? Просто е, ползвате ги, когато има смисъл да ги ползвате, но масото тези библиотеки НЕ стават за валидация в модела, понеже те взимат директно данните от $_REQUEST (и подобни), а модела взима от параметри. Имате няколко опции, едната е да хванете някой FormValidation, и да го модифицирате за работа с параметри на модела. Вариант 2, да си направите базов клас за модела, който реализира методите за валидация и да може да си опишете правилата. Вариант 3, статичен клас с методите за валидация, и на всеки метод на модела, ръчно си описвате всеки параметър.

Всеки един от тези варианти е добър, така че помислете, обмислете, разберете, и ако сте съгласни с мен, почнете да пишете валидациите където трябва. Ако ли не, майаната ми 🙂

Правила за защита от XSS атаки

Предполагам сте изгледали видеото, в което обяснявам какво е XSS. Тук ще се опитам да дам практически съвети за девелопърите как да избягват XSS.

Никога не вярвай на потребителя

Винаги валидирайте, нормализирайте и филтрирайте всички входящи данни. Това правило няма изключение и не се отнася само за XSS, а за всичко по принцип. Ето обикновено какво правя аз:

  • Прехвърлям всичко в UTF-8
  • Проверка дали дадена стойност идва
  • Махам интервалите в началото и края (trim)
  • Махам, ако има, повече от 1 интервал между думите $d = preg_replace('/\s\s+/', ' ', $_POST['comment']);
  • Проверявам за минимална/максимална дължина на текста, или големина на числото
  • Ако има проблем до тук слагам стойност по подразбиране.

До тук не сме направили нищо, което пряко да ни предпази от XSS, но пък XSS понякога върви в комбинация с други трикове, а част от тях вече са спрени, ако сме се убедили, че входните данни са чисти, и в последствие спокойно може да работим с тях. Респективно е показана грешка на потребителя, и кода не се е изпълнил, ако има проблем с тях.

Използвайте bbcode

Ако bbcode е подходящо за вашето приложение, то тогава вземете готова bbcode библиотека, или следвайки идеята на bbcode направете собствена имплементация. Идеята е проста, всичко което постъпва от потребителя минава през strip_tags(), което премахва всички html тагове. По този начин, почти не остава начин за изпълнение на XSS, но пък се губи форматирането. strip_tags() свежда всичко до текст без тагове. Единият вариант е да разрешите серия тагове, като b,i и подобни, но това не е добра идея. Понеже bbcode има собствени тагове, те минават, и в последствие, в сигурна среда тези bb тагове се конвертират в съответните b,i и подобни.

Ако няма да използвате bbcode по някаква причина, то тогава трябва да:

Изчистите най-вероятните причинители на XSS

Задължително трябва да прехвърлите определени знаци, в съответните им HTML entry и да ги изпращате към браузъра само в този вид. Задължително трябва да конвертирате:
& -> &
< -> &lt;
> -> &gt;
“ -> &quot;
‘ -> &#x27;
/ -> &#x2F;
Всеки език има функции или обекти да направи това прехвърляне. Хубавото на това е, че когато браузъра види &lt; ще го визуализира като < тоест <script ще бъде пратено като &lt;script , и бразузъра няма да го изпълни като javascript.

Прекарвайте всичко през подобно филтриране, не само „текстовете“

Примера до тук бе с текстово поле за коментар, но това не значи, че само от там може да се изпълни XSS. На практика, ако позволите на някой да „пише“ по вашия html, без значение дали това е коментар, URL на снимка, CSS дефиниция или каквото и да е, то той може да изпълни XSS атака. Ако сте пропуснали – „Никога не вярвайте на потребителя“

Пазете оригинала на данните

Това не е правило, а по-скоро идея, която аз използвам. Когато обработвам данните от потребителя, ако засека намек за XSS, тоест усетя, че има някой от знаците като <> записвам оригиналните непроменени данни в лог, заедно с данни за потребителя. Така лесно може да се проследи, кой какво и как се опитва да хитрува. Внимавайте колко записвате, ако сайта е посещаван, бързо може да съберете гигабайти. Не слагайте тези неща в базата, по-добре е в текстови лог.

Не слагайте лични данни и „коментари“ на една страница

XSS не е само за крадене на сесия, XSS може да вземе цялата HTML страница, или част от нея, и да я изпрати на някой сървър. Тоест ако на страницата за „профил“ на потребителя имате някакво поле, чийто данни идват от външни потребители, то ако мине XSS атака, този код, ще може да вземе цялата страница с всички данни на потребителя. Ако дизайна или друго ви налага да сте в такава ситуация, то тогава измислете начин да не сте. Опасно е! Ако все пак не можете, намерете начин да объркате показаната информация. Използвайте някой от методите за защита на показан email. Тоест JS прави така, че дадени текстове да се виждат от човек, но да са абсолютно безсмислени за код. Все пак, промяната в дизайна е по-добрата опция.

HTTPOnly флаг на бисквитките

Всеки език позволява да вдигнете този флаг, и повечето браузъри го спазват. Това което прави е, че не позволява на JS да чете тези бисквитки. Тоест ако мине XSS, то кода не може да види бисквитките с този флаг, тоест няма кражба на сесия. Винаги го ползвайте за сесийните бисквитки.

Направете отпечатък на браузъра

Когато стартирате сесия на потребителя направете хеш от вид и версия на ОС и Браузър.

$fingerprint=md5($_SERVER[‘HTTP_USER_AGENT’]);

Може да запишете и оригинала, без хеширане, въпрос на избор, но идеята е, при следващи заявки да проверявате дали отпечатъка отговаря с оригиналния. Ако има XSS и сесията бъде открадната, трябва и отпечатъка да съвпадне, което е още една защита. Ако отпечатъка не отговаря, нещо се е случило. Може потребителя да е обновил браузъра си, но това се случва рядко, и си заслужава да има тази защита.

Алгоритъм за разстояние

Използвайте geoIP за да намерите приблизителното местоположение на потребителя. PHP има добра библиотека за целта. При стартиране на сесия засичате потребителя на ниво град, и при всяка следваща заявка проверявате дали е в този район. Не може за 30 минути да отиде от София до Варна. Има доста примери по темата в интеренет. Тази защита се брои за доста напреднала, така че правете я само ако знаете какво правите понеже:

На IP не може да се разчита

Голяма част от хората са с динамични IP адреси, други минават (доброволно или не) през прокси сървъри, и е възможно 2 заявки от един и същи потребител, да дойдат от 2 различни адреса, дори и заявките да са в рамките на секунда. Някой доставчици правят нещата още по-зле, като AOL , понеже при тях всяка заявка е с различно IP, и на всичко отгоре е и от различен град.

Не стряскайте потребителя

Ако засечете нещо, което ви изглежда нередно, и може да е следствие от XSS, не вадете големите червени екрани, и не стряскайте потребителите. Може заради неразбиране, грешка, или извънземните, нещо да се е объркало. В този случай просто помолете отново за парола, както го правят google. Ако е XSS, кракера има сесия, но не и парола. Елегантно и спокойно помолете потребителя да си въведе паролата, и ако е ОК, значи е ОК.  Ако не е ОК, вие вече сте унищожили сесията 🙂

Направете си своя библиотека за филтриране

XSS е пряко свързан с браузъра, и както излизат нови версии, така се появяват и нови „хакове“. Опитайте се да съберете всички правила във собствен клас, които да може да разширявате в последствие.

Проверете вашия клас

Може да влезете тук и да намерете списък на почти всички известни XSS „врътки“. Там няма да видите код за чист XSS, а просто техниката, по която може да вкарате JS в браузъра. Тоест, прекарайте примерете през вашия клас, и ако мине, значи имате проблем. Някой от примерите са специфични на конкретен браузър, примерно бъг на IЕ в енкодинга, така че трябва да тествате библиотеката си и през различните браузъри.

Мултитъч ама без тъч екран

Ето една демонстрация на мултитъч технология, без тъч екран, която се подготвя в за новото Ubuntu. Използва се стандартна Web камера, която разпознава движението на ръцете, и инжектира събитието директно в кернел, което значи, че всеки един софтуер ще работи с тази система. Ето вижте 🙂

А това е демонстрация на скорост при стандартен мултитъч

Както се казваше в един филм „Найс, а?“

HDTV

Що е то HDTV и има ли то почва у нас.Аз специално съм клиент на BLIZOO и с неудоволствие установих,че HD каналите който предлагат са с малко по добро от цифровата.С изключение на евроспорт но имам чувството че това са просто HD пуснати по „обновен“ начин.Благодаря ти предварително.

Какво е AJAX

Може ли да направиш едно бързо обощение какво е това живтно, с какво се храни и каде обитава. В нета не оспях да намеря инфо което да разгадя, но пък е и по-лесно някой добър презентатор да обясни Мерси предварително.
PS:Оправих проблема с фокуса на камерата, за напред няма да го има 🙂

Малко Linux статистика

Наскоро Linux Foundation публикуваха доста интересни статистики за развитието на Linux кернела. Като цяло документа (цък за PDF) дава яснота, кой го пише, как го пише, защо го пише. Ето няколко сбити цифри.

  • време между 2 версии 81 дни
  • брой промени между версиите ~ 9000
  • среден брой одобрени пачове на час 5.18
  • 15531 реда код са променяни всеки ден (добавени, изтрити, редактирани)
  • последната версия на кернела има 13,468,253 реда код и се увеличават с 9,058 всеки ден
  • средно 659 компании и 6117 разработчика се грижат за проекта
  • над-активните 30 разработчика са направили 22% от всички промени по ядрото
  • 30% от всичката работа е свършена от хора на добра воля, в свободното им време.

Доста впечатляващи цифри. Опитах се да намеря референтна статистика за MS или Apple, за да сравним как са там нещата, но не можах.

Извода е, че Линукс разработката си се прави от ентусиасти в свободното им време, но не в мазетата и не от аматьори, и скоростта на развитие се увеличава линейно с времето.

PS: моля не захапвайте пак Linux VS Wilindows VS Apple VS извънземните.