ולידציה של טפסים – נקודה למחשבה.

אם יצא לכם לכתוב טופס כלשהו (לא בהכרח ב-HTML5, אם כי זה בהחלט משפר את השימושיות ופשוט להפליא), אני בטוח שיצא לכם להיאבק בשאלה – לוודא או לא לוודא. אלו מכם שבקיאים בנושא, מודעים לכך שכיום, דפדפנים הטמיעו מנגנוני ולידציה פשוטים וקלילים – כאלה שחוסכים הרבה כאב ראש למתכנת, שעד אז נאלץ לממש את מנגנוני האימות כל פעם מחדש ב-JavaScript. גם Angular וספריות אחרות מספקות מימוש אימות קליל באמצעותן. אבל האם אלו מספקים פתרון מקיף לבעיה?

מי בכלל צריך ולידציה?

בעבר ציינתי שאחד העקרונות החשובים ביותר לפיתוח מאובטח, הוא בדיקת קלט המשתמש. הולידציה, עקרון חשוב מאוד באבטחת הקוד שלנו, עוזרת לנו להימנע מנקודות קיצון שבהם אנו לא בטוחים כיצד הקוד שלנו יתמודד. יתרה מכך, עלול להיות מצב לא נעים, בו נגרום לתסכול של המשתמש, היות והוא לא הבין מה הוא מילא לא בסדר. אני מאמין שלכולנו היו חוויות בירוקרטיות נוראיות, בהן נאלצנו להגיש את הטופס שוב ושוב, כיוון שמישהו לא טרח להסביר כמו שצריך מה נדרש מאיתנו.

התשובה לשאלה שבראש הפיסקה היא כולנו. הן המשתמש צריך ולידציה כדי להשתמש בקלות באתר וכמובן שגם המתכנת צריך ולידציה כדי לוודא שהוא מכיר את כל מקרי הקיצון בקוד שלו.

מי אחראי לבצע את הולידציה? השרת או הדפדפן?

בשביל לענות על שאלה זו עלינו לזכור מספר נקודות חשובות. קוד צד הלקוח עלול להיות מושפע ממניפולציות של משתמש זדוני. לדוגמה, נניח ואני מעוניין שבשדה מספר טלפון, יוכנסו רק מספרים. בעבר, היה נהוג לבצע זאת באמצעות חסימה של הכנסת תווים שאינם מספרים באמצעות פונקציות JavaScript שנכתבו עבור הטופס. אולם, במידה והמשתמש היה מנטרל את JavaScript בהגדרות הדפדפן שלו, הרי שאימות הנתונים היה מנוטרל. במקרה כזה, אנו עלולים להגיע למצב בו מסד הנתונים יזרוק שגיאה למשתמש (חלילה), או יותר גרוע, מערכות עלולות לאבד מזמינותן, כיוון שינסו לגשת למספר טלפון שאינו מספר.

כמובן, שעלינו להיזהר לא רק מכיבוי תמים של JavaScript, אלא גם ממשתמשים זדוניים, כאלו שישתמשו בכל פיסת קוד שעליהם יוכלו להניח את ידיהם על מנת לנסות ולפרוץ למערכת שאנו בונים. אתן דוגמה. אתר פורומים מוכר היה מאפשר למשתמש להעלות שורת סטטוס שהוגבלה למספר תווים מצומצם. יתרה מכך, שורת הסטטוס הייתה נבדקת ומנוקה מתווי HTML בצד הלקוח באמצעות פונקציית JavaScript. במקרה זה, נטרול של ה-JavaScript בדפדפן אפשר למשתמשים להכניס לשורת הסטטוס תווי HTML וכן לחרוג ממגבלת התווים – ובכך להשפיע על עיצוב האתר. ההשפעה אמנם לא הייתה זדונית, אבל במקרה כזה לא מן הנמנע שניתן היה לנצל שדה קלט זה עבור פרצות חמורות יותר, כגון SQL Injections ו-Cross Site Scripting.

אם כך, אז מדוע שצד השרת לא יהיה אחראי על הולידציה? כיוון שבמידה וניתן לצד השרת לאמת את הנתונים בלבד, הרי שנפגע משימושיות הטופס. במידה ונמתין עד לשלב שבו המשתמש שלח את הטופס, אנו עלולים להשלות את המשתמש לחשוב שסיים למלא את הטופס (רק כדי לטרטר אותו לתקן את המסובך). לא נכנס לנקודה של קושי המימוש של הודעות שגיאה ברורות כאשר הולידציה היא רק בצד השרת (אם כי זו בהחלט נקודה בה עלינו להתחשב), וכמובן בבעית הביצועים של שליחת טופס מחדש שוב ושוב.

אם כך, מדובר בשאלה מכשילה, התשובה הרי היא: שני הצדדים אחראים במידה שווה לולידציה של טופס. כיום קל יותר מתמיד לפתח ולידציה בצד הלקוח, תודות לתקן HTML5 ולמימוש שלו באמצעות הדפדפנים השונים. במידה וטופס נבנה נכון, הרי שדפדפנים יחילו עליו ולידציות בסיסיות (לדוגמה שדות נדרשים למילוי טופס) באופן אוטומטי. בנוסף, מי מכם שתיכנת ב-Angular מכיר את הולידציה הפנימית שמאפשרת Angular לטפסים. טכנולוגיות אלו מאפשרות לבנות בקלות טפסים פשוטים, רספונסיביים וברורים למשתמש, שמאמתים את עצמם ולא מאפשרים שליחה של טופס לא מאומת. אולם, ולידציות בצד הלקוח ניתן (בקלות יחסית) לנטרל, ועל כן עלינו לספק שכבת ולידציה גם בצד השרת, בטרם הנתונים יעברו עיבוד משמעותי (לדוגמה, הכנסתם למסד הנתונים).

איך מבצעים ולידציה באמצעות הפדפדן? 

זו שאלה שקשה מאוד לענות עליה על רגל אחת. בגדול, צריך בסך הכל להיצמד לכללים של HTML5 ליצירה של טפסים. אנסה לתאר מעט כללי אצבע, אבל לרוב מדובר במימושים ספציפיים לכל דפדפן בנפרד. דפדפנים עדכניים מחילים אימות נתונים כברירת מחדל בטפסים. במידה ונרצה לבטל (מסיבה כלשהי), נצטרך להוסיף את התכונה novalidate לטופס. בנוסף, חשוב לזכור שהיות ומדובר במימוש של הדפדפן, הודעות השגיאה (באם יש כאלו), יוצגו בעיצוב שעליו לא נוכל להשפיע (לרוב מכוער), וזה עלול לפגוע בחוויית הגלישה באתר. כמו כן, ולידציה באמצעות הדפדפן תלוייה בגרסת הדפדפן של המשתמש, ולא ניתן להסתמך עליה.

  • בשדות נדרשים נכניס את התכונה Required.
  • בשדות שמכילים מבנה מיוחד (לדוגמה, שדה הכנסת אימייל) נדאג לציין עבור הדפדפן את סוג השדה. לדוגמה, input type="email".
  • בשדות שבהם נדרש להכניס רק ספרות, נשתמש ב-input type="number". ניתן גם לספק טווח מספרים (range).
  • במידה ומאיזושהי סיבה החלטנו לתת ערך ברירת מחדל בתאי קלט, נדאג לוודא שהוכנס תוכן חדש.
  • במידה ונדרשת מחרוזת ספציפית, ניתן להכניס את התכונה Pattern ולספק Regular Expressions של הביטוי שנדרש.
  • במבט ראשון לא ניתן יהיה לשלוח את הטופס במידה ואחד מהתאים אינו תקין (כמובן שאין להסתמך על זה).

מהי ולידציה באמצעות Angular?

ניתן כמובן לבצע ולידציה גם באמצעות Angular. הספרייה הפופולרית לפיתוח בצד הלקוח מספקת פתרון מקיף לולידציה בצד הלקוח. היתרון הגדול של מימוש בצורה זו הוא, שבניגוד לולידציה של הדפדפן, Angular מספקת לנו ממשק נוח מאוד להתחבר, לעצב ולהציג את תוצאות הולידציה בקלות יחסית, באמצעות הוספת CSS Classes פשוטים. היא אינטואיטיבית וברורה, קלה למימוש ומאפשרת ליצור בקלות יחסית טפסים ברמה גבוהה מאוד. החסרון הגדול הוא, שכמו כל מנגנון ולידציה ב-JavaScript, ניתן לערוך אותו, להשפיע עליו ולנטרל אותו מצד המשתמש.

אם בכוונתכם לבצע ולידציה של טופס באמצעות Angular, שימו לב לנקודות הבאות:

  • עליכם לנטרל את מנגנון הולידציה האוטומטית של הדפדפן באמצעות תכונת novalidate בתג הטופס.
  • Angular מספקת בעבורכם לכל תג מספר אינדיקטורים בוליאניים של מצבים, השתמשו בהם –
    • $untouched – המשתמש לא נגע בשדה.
    • $touched – המשתמש נגע בשדה.
    • $pristine – הערך בשדה לא השתנה עדיין.
    • $dirty – הערך בשדה השתנה, המשתמש הזין משהו לתוכו.
    • $invalid/$valid – הערך בשדה לא תקין\תקין.
  • לדוגמה, באפשרותכם להוסיף ולהסיר מחלקות מתגים, במידה והאינדיקטור שלו מצביע ש-$valid אמת, או שהוא $invalid.
  • באפשרותכם לבטל את האפשרות לשלוח את הטופס ובכך למנוע טעויות אנוש וכו'.

לסיכום

ולידציה היא אלמנט חשוב בכל טופס, ויכולה לתרום לשימושיות ולחוויית השימוש של המשתמש באתר. אסור בשום פנים ואופן לוותר על ולידציה בצד השרת, וכמובן שאין להסתמך בשום שלב שהמשתמש הזין פרטים תקינים. במידת האפשר, נסו לצמצם עבור המשתמש את האפשרויות (לדוגמה, מנעו הכנסת קלט חופשי במידה והמשתמש יכול להזין רק מספר מועט של ערכים), שמרו על המשתמש מהטעויות של עצמו ועל עצמכם ממשתמשים ערמומיים. בהצלחה!

הוסף תגובה