<meta http-equiv='pics-label' content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline EN v2.0" l gen true for "http://interval.cz" r (nz 1 vz 1 lz 1 oz 1 cz 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://interval.cz" r (n 0 s 0 v 0 l 0))' />
<p id='prepend'>SystΘmy CAPTCHA zis¥uj·, s k²m aplikßcia komunikuje, respektφve zabezpeΦuj·, ₧e aplikßcia nekomunikuje so "strojom", ale so skutoΦn²m Φlovekom. Vo webov²ch aplikßcißch sa CAPTCHA najΦastejÜie vyu₧φva pri prihlasovanφ sa do aplikßcie Φφm sa zaruΦuje, ₧e do aplikßcie sa prihlasuje skutoΦn² Φlovek a nie automat, robot. V tomto Φlßnku si priblφ₧ime princφpy CAPTCHA a vytvorφme si ASP.NET ovlßdacφ prvok, ktor² sa dß bez problΘmov pou₧i¥ v ╛ubovo╛nej webovej aplikßcii.</p>
<p>CAPTCHA (<em>Completely Automated Public Turing test to tell Computers and Humans Apart</em>) by sa dalo vo╛ne prelo₧i¥ ako "automatick² sp⌠sob ako rozlφÜi¥ stroj od Φloveka". Viac informßciφ nßjdete naprφklad na strßnkach <a href='http://www.captcha.net'>The CAPTCHA Project</a>.</p>
<h3>Ako funguje CAPTCHA</h3>
<p>Preto₧e poΦφtaΦe nedokß₧u (aspo≥ nie dostatoΦne spo╛ahlivo) "rozumie¥" obrßzkom, je systΘm CAPTCHA zalo₧en² na obrßzkoch najrozÜφrenejÜφm z t²chto systΘmov. Princφp je jednoduch² - aplikßcia vygeneruje obrßzok, na ktorom je k≤d (text, Φφslo, grafick² objekt, fotografia), ktor² je ╛ahko porozumite╛n² pre Φloveka, ale ¥a₧ko pre poΦφtaΦ. U₧φvate╛ musφ k≤d z obrßzka zada¥ do textovΘho po╛a. Aplikßcia si k≤d na vstupe porovnß s t²m, ktor² vygenerovala do obrßzka. Ak s· k≤dy zhodnΘ, tak je vysoko pravdepodobnΘ, ₧e s aplikßciou komunikuje Φlovek.</p>
<p>Pou₧itie systΘmu CAPTCHA pri prihlasovanφ sa do aplikßcie mß aj ∩alÜφ ve╛mi d⌠le₧it² "ved╛ajÜφ efekt" - zabra≥uje hßdaniu hesiel hrubou silou. ┌tok normßlne funguje tak, ₧e nejak² automat (program, robot) sk·Üa za sebou vÜetky kombinßcie znakov ako heslo a sk⌠r Φi nesk⌠r heslo do systΘmu musφ zφska¥. Pri zabezpeΦenφ prihlasovania CAPTCHA systΘmom ale aplikßcia vygeneruje pri ka₧dom pokuse o prihlßsenie nov² obrßzok s k≤dom. Najprv sa skontroluje sprßvnos¥ CAPTCHA k≤du, ak je nesprßvny, pokus o prihlßsenie sa konΦφ ne·spechom a teda eÜte sk⌠r, ako sa v⌠bec kontroluje sprßvnos¥ zadanΘho hesla. Z bezpeΦnostnΘho hladiska musφ v₧dy plati¥, ₧e po ka₧dom (sprßvnom aj nesprßvnom) pokuse o prihlßsenie sa musφ vygenerova¥ nov² CAPTCHA k≤d.</p>
<div class='image'>
<img src='podklady/hlavaty/1134/gmail.png' title='CAPTCHA na Gmaile' alt='CAPTCHA na Gmaile' />
<br /><span class='comment'>Aj Gmail sa proti hßdaniu hesiel hrubou silou brßni systΘmom CAPTCHA</span>
</div>
<p>V jednom z predoÜl²ch Φlßnkov som vßm ukßzal, ako Φo najefektφvnejÜie generova¥ obrßzky na strane servra. Prφklad vÜak nemal ve╛kΘ vyu₧itie v praxi. Teraz si tento prφklad rozÜφrime a vytvorφme ovlßdacφ prvok CAPTCHA, ktor² nßjde vyu₧itie prakticky v ka₧dej webovej aplikßcii.</p>
<h3>Http handler na generovanie obrßzka</h3>
<p>Zdrojov² k≤d http handlera, ktor² bude generova¥ obrßzok s CAPTCHA k≤dom, je prakticky rovnak² ako v Φlßnku <a href='http://interval.cz/clanek.asp?article=3678' title='Hlavat², DuÜan: DynamickΘ obrßzky v ASP.NET cez HTTP handler'>DynamickΘ obrßzky v ASP.NET cez HTTP handler</a>. V met≤de <code>ProcessRequest(HttpContext context)</code> vÜak upravφme Φas¥, v ktorej vykres╛ujeme samotn² text. Ten zobrazφme nßhodne zdeformovan², aby bol horÜie Φitate╛n²m pre poΦφtaΦ:</p>
<div class='sample'>
...
<br /><span class='comment'>// Nastavime format textu</span>
<br />Brush hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray);
<br />g.FillPath(hatchBrush, path);
<br />...
</div>
<p>V met≤de si najprv vytvorφme cestu (trieda <code>GraphicsPath</code>) s CAPTCHA k≤dom. Cestu nßhodne deformujeme met≤dou <code>Warp(...)</code>. A nakoniec vyplnφme pomocou <code>FillPath(...)</code>. NßÜ CAPTCHA obrßzok bude vyzera¥ naprφklad takto:</p>
<p>Zßsadou je - Φφm viac ruÜiv²ch elementov sa v obrßzku nachßdza (Üum, r⌠zne Φiary a podobne), t²m je pre prφpadnΘho ·toΦnφka ¥a₧Üie tento systΘm prekona¥ a vytvori¥ automat, ktor² by vedel k≤d spo╛ahlivo Φφta¥.</p>
<h3>Ovlßdacφ prvok CAPTCHA v ASP.NET</h3>
<p>Ovlßdacφ prvok bude obsahova¥ obrßzok so samotn²m CAPTCHA k≤dom a textovΘ pole, kam bude u₧φvate╛ tento k≤d vklada¥. Ovlßdacφ prvok bude tie₧ validßtorom, Φi₧e bude aplikßcii oznamova¥, ₧e u₧φvate╛ zadal nesprßvny k≤d.</p>
<p>Ovlßdacφ prvok <strong>musφ</strong> pri <strong>ka₧dom</strong> svojom "vykres╛ovanφ" vygenerova¥ nov² CAPTCHA k≤d. Tento ulo₧φ do sessiony, odkia╛ si ju vyzdvihne http handler a vykreslφ ho. Pri post-backu formulßra sa k≤d zadan² u₧φvate╛om porovnß s t²m, ktor² je v session. Ak nie s· k≤dy rovnakΘ, validßtor oznßmi aplikßcii chybu.</p>
<p>Vytvorφme si teda triedu pre nßÜ ovlßdacφ prvok - ten bude dedi¥ z triedy <code>System.Web.UI.Control</code>:</p>
<div class='sample'>
public class CaptchaControl : System.Web.UI.Control, IValidator, INamingContainer
<p>Trieda bude ma¥ nieko╛ko verejne prφstupn²ch premenn²ch. Adresa nßÜho http handlera, ktor² generuje samotn² obrßzok s k≤dom, sa bude nastavova¥ pomocou <samp>Url</samp>. (Nezabudnite, ₧e handler musφ by¥ sprßvne zaregistrovan².) Otvßracφ HTML tag nßÜho prvku je v premennej <samp>TagKey</samp>. A CSS trieda je v <samp>CssClass</samp>.</p>
<p>VÜetky kompozitnΘ ovlßdacie prvky by mali vytvßra¥ svojich "potomkov" v met≤de <code>CreateChildControls()</code>. My v tejto met≤de vytvorφme textovΘ pole <samp><input type="password" ...></samp> a pridßme ho do kolekcie <code>Controls</code>.</p>
<br /> writer.Write( "Zadaj k≤d ktor² vidφÜ na obrßzku:" );
<br /> writer.RenderEndTag();
<br />
<br /> this.RenderChildren( writer );
<br /> writer.RenderEndTag();
<br /> writer.RenderEndTag();
<br />
<br />}
</div>
<p>V met≤de najprv "vykreslφme" <samp><img ...></samp> element, ktor² zobrazuje CAPTCHA k≤d, potom oznam pre u₧φvate╛a a napokon textovΘ pole pre zadßvanie tohto k≤du. NßÜ ovlßdacφ prvok bude generova¥ tak²to HTML k≤d:</p>
<p>Ako som u₧ spomφnal, ovlßdacφ prvok <strong>musφ</strong> pri <strong>ka₧dom</strong> svojom "vykres╛ovanφ" vygenerova¥ nov² k≤d. Preto pridßme do naÜej triedy met≤du, ktorß nßm toto spo╛ahlivo zabezpeΦφ - vygeneruje trojcifernΘ Φφslo a ulo₧φ ho do sessiony:</p>
<p>NßÜmu ovlßdaciemu prvku ch²ba u₧ len poslednß vec - kontrola sprßvnosti u₧φvate╛om zadanΘho k≤du. Ovlßdacφ prvok je preto zßrove≥ aj validßtorom a implementuje rozhranie <code>IValidator</code> (Viac o validßtoroch sa doΦφtate v Φlßnku <a href='http://interval.cz/clanek.asp?article=1278' title='Naiman, Michal: ASP.NET - schvalovacφ prvky'>ASP.NET - schvalovacφ prvky</a>). V met≤de <code>Validate()</code> najsk⌠r zistφme, Φi nßÜ ovlßdacφ prvok je vidie¥. Ak nie, tak vlastnos¥ <code>IsValid</code> vrßti <samp>true</samp>, Φi₧e ₧iadna chyba sa nevyskytla. Ak prvok je vidie¥, tak zavolßme met≤du <code>EvaluateIsValid</code>, ktorß naΦφta zo sessiony aktußlny k≤d a porovnß ho s k≤dom, ktor² zadal u₧φvate╛. Ak s· rovnakΘ, vrßti <samp>true</samp>, inßΦ vrßti <samp>false</samp>. No a eÜte do triedy pridßme vlastnos¥ <samp>ErrorMessage</samp>, ktorß obsahuje chybov· hlßÜku. Implementßcia nßÜho validßtora vyzerß nasledovne:</p>
<div class='sample'>
public void Validate()
<br />{
<br /> if (!this.IsVisible)
<br /> {
<br /> this.isValid = true;
<br /> return;
<br /> }
<br /> this.isValid = this.EvaluateIsValid();
<br />}
<br />
<br />protected virtual bool EvaluateIsValid()
<br />{
<br /> // ak uzivatel nic nezadal tak konec
<br /> if (this.inputText.Value.Length == 0)
<br /> {
<br /> return false;
<br /> }
<br />
<br /> object o = Context.Session[ CaptchaHttpHandler.SESSION_CaptchaKey ];
<br /> if ( !(o is string) )
<br /> {
<br /> return false;
<br /> }
<br />
<br /> string generated = (string)o;
<br /> if (generated.Equals(this.inputText.Value))
<br /> {
<br /> return true;
<br /> }
<br /> return false;
<br />}
<br />
<br />private bool isValid = true;
<br />
<br />public bool IsValid
<br />{
<br /> get
<br /> {
<br /> return this.isValid;
<br /> }
<br /> set
<br /> {
<br /> this.isValid = value;
<br /> }
<br />}
<br />
<br />private string errorMessage;
<br />
<br />public string ErrorMessage
<br />{
<br /> get
<br /> {
<br /> return this.errorMessage;
<br /> }
<br /> set
<br /> {
<br /> this.errorMessage = value;
<br /> }
<br />}
</div>
<p>Pre sprßvnu funkΦnos¥ musφme eÜte nßÜ prvok pri inicializßcii zaregistrova¥ medzi ostatnΘ validßtory na strßnke:</p>
<div class='sample'>
protected override void OnInit(EventArgs e)
<br />{
<br /> base.OnInit (e);
<br /> <span class='comment'>// pridame ov. prvok medzi ostatne validatory:</span>
<br /> this.Page.Validators.Add(this);
<br /> this.EnsureChildControls();
<br />}
</div>
<h3>Ovlßdacφ prvok v praxi</h3>
<p>NßÜ ovlßdacφ prvok je hotov² a m⌠₧me ho zaΦa¥ pou₧φva¥ pri prihlasovanφ u₧φvate╛ov, alebo naprφklad aj pri overovanφ, Φi u₧φvate╛ naozaj chce vykona¥ nejak· deÜtruktφvnu operßciu. ("Chcete naozaj stornova¥ fakt·ru? Zadajte k≤d, ktor² vidφte na obrßzku...")</p>
<p>Ja som pripravil jednoduch· ASPX strßnku, na ktorej si m⌠₧eme <a href='http://aspx.interval.cz/hlavaty/1134/'>overi¥ funkΦnos¥ ovlßdacieho prvku</a>. Cel² <a href='podklady/hlavaty/1134/captcha_solution.zip'>zdrojov² k≤d</a> nßjdete v prilo₧enom s·bore. Nemß v²znam uvßdza¥ cel² k≤d do Φlßnku - ukß₧eme si iba ako v obsluhe tlaΦidla zistφme, Φi sa na strßnke vyskytla chyba a teda Φi u₧φvate╛ zadal sprßvny k≤d. Je to jednoduchΘ:</p>
<p>NßÜ ovlßdacφ prvok nie je dokonal² a ani sa nesna₧φ by¥. Mß nieko╛ko obmedzenφ a mo₧nΘ bezpeΦnostnΘ slabiny. Obmedzenφm je naprφklad jeho vzh╛ad (respektφve generovan² HTML k≤d), ktor² je pevne dan² a meni¥ sa dß len pomocou CSS. Nov² CAPTCHA k≤d sa generuje pri ka₧dej po₧iadavke (request) na server - Φo je samozrejme sprßvne. Ale aj obrßzok s k≤dom sa generuje pri ka₧dej po₧iadavke (requeste na nßÜ http handler). To m⌠₧e by¥ bezpeΦnostnß slabina. Ak poÜleme na server naprφklad 10 po₧iadaviek, zaka₧d²m server vygeneruje in² obrßzok (preto₧e ho nßhodne deformujeme), na ka₧dom vÜak bude ten ist² k≤d. Toto m⌠₧e vyu₧i¥ sofistikovan² robot, ktor² bude posiela¥ po₧iadavky na CAPTCHA obrßzok, k²m si nebude ist², ₧e k≤d na ≥om rozpoznal. Potom tento k≤d vlo₧φ do textovΘho po╛a. S· aplikßcie (naprφklad u₧ spomφnanΘ stornovanie fakt·ry v intranetovej aplikßcii), kde tßto slabina nemusφ prekß₧a¥. V ostatn²ch vÜak treba zabezpeΦi¥, aby pri ka₧dej po₧iadavke server vrßtil rovnak² obrßzok, a₧ dok²m sa nevygeneruje nov² CAPTCHA k≤d...</p>
<div class='page-right-box reading'><h3 title='NejΦten∞jÜφ Φlßnky za poslednφch 14 dn∙'>NejΦten∞jÜφ</h3><div class='page-right-box-in'><ul><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3829'>Interval.cz a jeho Φtenß°i v roce 2005</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3830'>Pou₧φvßme nßvrhovΘ vzory v .NET - Singleton</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3827'>SUN Java Studio Creator</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3824'>Perl-compatible regulßrnφ v²razy v PHP - modifikßtory a lφnΘ kvantifikßtory</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3831'>GNU Gettext - sprßva p°eklad∙</a></li></ul></div></div><div class='page-right-box cauldron'><h3 title='Nejdiskutovan∞jÜφ Φlßnky za poslednφch 21 dn∙'>Diskuznφ kotel</h3><div class='page-right-box-in'><ul><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3818' title='(36 komentß°∙)'>PHP a MS SQL - vklßdßnφ a naΦφtßnφ soubor∙</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3811' title='(26 komentß°∙)'>GNU Gettext - prvnφ kroky</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3829' title='(20 komentß°∙)'>Interval.cz a jeho Φtenß°i v roce 2005</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3815' title='(11 komentß°∙)'>H°φchy pro ÜφlenΘho korektora - jak se vyhnout zbyteΦn²m chybßm</a></li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3825' title='(11 komentß°∙)'>Ovlßdacφ prvok CAPTCHA v ASP.NET</a></li></ul></div></div>