كنترل های Validation در ASP.NET
در اين مقاله به بررسی امكانات ارائه شده در ASP.NET به منظور ارزيابی صحت داده ورودی خواهيم پرداخت . آشنائی و بكارگيری روش های مناسب به منظور بررسی صحت داده ورودی يكی از عمليات مهم در جهت ايمن سازی برنامه های وب نيز می باشد . پس با انگيزه و دقت مضاعف كار را دنبال می نمائيم .
ضرورت و ماهيت كنترل های Validation
به منظور ارزيابی داده ورودی توسط كاربران با توجه به داده مورد نياز اسكريپت ها ، از روش های متعددی می توان استفاده نمود . متداولترين نياز ، وجود يك مقدار ورودی است . در چنين مواردی ، انتظار داريم قبل از اين كه يك اسكريپت بتواند پردازش های مورد نياز را بر روی داده ورودی انجام دهد، در TextBox مقداری درج شده باشد. ماهيت داده ورودی در اين مقطع مهم نمی باشد و مهم اين است كه داده ئی توسط كاربر در مكان مورد نظر وارد شده باشد . در برخی موارد لازم است كه داده ورودی از يك نوع خاص باشد ( به عنوان نمونه يك مقدار عددی ) تا بتوان آن را در اختيار روتين های مورد نظر به منظور انجام پردازش های محاسباتی قرار داد . در برخی موارد ديگر ، لازم است كه داده ورودی در يك محدوده خاص باشد و داده درج شده خارج از محدوده مورد نظر ، غيرمعتبر گردد .
برای بررسی و ارزيابی صحت داده در ASP.NET مجموعه ای از كنترل های validation ارائه شده است . از كنترل های فوق می توان به منظور بررسی و تست عدم درج داده ، مقايسه داده ورودی با يك مقدار خاص ، بررسی وجود مقادير در يك محدوده خاص و ساير فرم های داده استفاده نمود تا اين اطمينان ايجاد گردد كه داده مناسب و معتبر در اختيار اسكريپت ها و به منظور انجام پردازش ها قرار داده می شود .
كنترل های validation در ارتباط مستقيم با كنترل TextBox بوده و تست و ارزيابی خود را بطور اتوماتيك و پس از كليك بر روی كنترل هائی نظير Button ، LinkButton و ImageButton انجام خواهند داد . در صورتی كه ماحصل بررسی يك كنترل validation توام با موفقيت نباشد ، validator يك پيام خطاء را نمايش و به كاربران اعلام می نمايد كه داده ورودی فاقد شرايط لازم برای استفاده در برنامه می باشد .
در ادامه به بررسی كنترل های فوق خواهيم پرداخت .
كنترل <asp:RequiredFieldValidator>
شكل عمومی
<asp:RequiredFieldValidatorid="id" Runat="Server" |
توضيحات
• به خصلت ControlToValidate ، مقدار id كنترل textBox كه مسئوليت بررسی آن به كنترل RequiredFieldValidator واگذار شده است ،نسبت داده می شود.
• خصلت ErrorMessage ، پيام مورد نظر در صورت بروز خطاء را مشخص می نمايد .
• خصلت SetFocusOnErrorMessage ، يك blinking cursor را در كنترل TextBox مربوطه به منظور تسهيل در امر درج داده جديد قرار می دهد .
• خصلت ValidationGroup يك گروه از كنترل های TextBox را كه مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نمايد (در مواردی كه دكمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .
• خصلت Display : كنترل RequiredFieldValidator ، يك فضای افقی را متناسب با طول رشته مربوط به پيام خطاء اشغال خواهد كرد . در اغلب موارد ، پيام خطاء در كنار TextBox مربوطه نمايش داده می شود . مكان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو اين كه خطائی اتفاق نيافتد ) . در صورتی كه مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مكانی برای نمايش پيام خطاء رزو نخواهد شد و بطور پويا و همزمان با بروز خطاء ايجاد می گردد .
مثال
در اين مثال زمانی كه كاربر بر روی button كليك نمود ، كنترل RequiredFieldValidator بطور اتوماتيك عمليات بررسی و ارزيابی داده ورودی در TextBox را آغاز می نمايد ( قبل از اين كه روتين Get_Data فراخوانده شود ) . در صورتی كه TextBox خالی باشد ، يك پيام خطاء نمايش داده شده و cursor مجددا" در TextBox قرار خواهد گرفت . در صورتی كه در TextBox داده ئی توسط كاربر درج گردد ، تست ارزيابی با موفقيت انجام و روتين مربوط فراخوانده شده و مقدار ورودی را در خروجی نمايش خواهد داد . در اين مثال ، مقدار خصلت Display كنترل RequiredFieldValidator ، معادل Dynamic در نظر گرفته شده است ، بنابراين در صورت عدم توليد يك پيام خطاء ، مكانی بر روی صفحه برای نمايش آن در نظر گرفته نخواهد شد . بدين ترتيب به كنترل label اجازه داده می شود كه در كنار TextBox نمايش داده شده و از فضای مشابه پيام خطاء استفاده نمايد ( استفاده مشترك از يك مكان بر روی فرم وب به منظور نمايش پيام خطاء و يا داده ورودی توسط كاربر ) .
<SCRIPT Runat="Server"> |
كنترل <asp:RangeValidator>
شكل عمومی
<asp:RangeValidatorid="id" Runat="Server" |
توضيحات
• خصلت ErrorMessage ، پيام مورد نظر در صورت بروز خطاء را مشخص می نمايد .
• خصلت SetFocusOnErrorMessage ، يك blinking cursor را در كنترل TextBox مربوطه به منظور تسهيل در امر درج داده جديد قرار می دهد .
• خصلت ValidationGroup يك گروه از كنترل های TextBox را كه مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نمايد (در مواردی كه دكمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .
• خصلت Display : كنترل RangeValidator ، يك فضای افقی را متناسب با طول رشته مربوط به پيام خطاء اشغال خواهد كرد . در اغلب موارد ، پيام خطاء در كنار TextBox مربوطه نمايش داده می شود . مكان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو اين كه خطائی اتفاق نيافتد ) . در صورتی كه مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مكانی برای نمايش پيام خطاء رزو نخواهد شد و بطور پويا و همزمان با بروز خطاء ايجاد می گردد .
• خصلت Type : در صورتی كه نوع داده ورودی مشخص نگردد ، نوع آن به صورت پيش فرض string در نظر گرفته خواهد شد . يك TextBox خالی ، به عنوان يك نوع داده معتبر ارزيابی خواهد شد . بنابراين ، لازم است كه به همراه كنترل RangeValidator از يك كنترل RequiredFieldValidator نيز استفاده گردد تا اين اطمينان حاصل شود كه با عدم درج داده در TextBox مربوطه با آْن به عنوان يك داده معتبر برخورد نخواهد شد .
• خصلت های MinimumValue و MaximumValue ، حداقل و حداكثر محدوده مجاز برای داده ورودی را مشخص می نمايند .
مثال
در اين مثال به منظور ارزيابی و تست داده ورودی در يك TextBox از دو كنترل RangeValidator و RequiredFieldValidator استفاده شده است . بنابراين می بايست حتما" در TextBox مقداری درج گردد . با توجه به اين كه مقدار خصلت Type معادل integer و مقادير خصلت های MinimumValue و MaximumValue به ترتيب صفر و نه در نظر گرفته شده اند ،داده ورودی می بايست عددی بين صفر تا نه باشد .
<SCRIPT Runat="Server"> |
كنترل <asp:CompareValidator>
شكل عمومی
<asp:CompareValidatorid="id" Runat="Server" |
توضيحات
• به خصلت ControlToValidate ، مقدار id كنترل textBox كه مسئوليت بررسی آن به كنترل <asp:CompareValidator> واگذار شده است ،نسبت داده می شود.
• خصلت ErrorMessage ، پيام مورد نظر در صورت بروز خطاء را مشخص می نمايد .
• خصلت SetFocusOnErrorMessage ، يك blinking cursor را در كنترل TextBox مربوطه به منظور تسهيل در امر درج داده جديد قرار می دهد .
• خصلت ValidationGroup يك گروه از كنترل های TextBox را كه مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نمايد (در مواردی كه دكمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .
• خصلت Display : كنترل <asp:CompareValidator> ، يك فضای افقی را متناسب با طول رشته مربوط به پيام خطاء اشغال خواهد كرد . در اغلب موارد ، پيام خطاء در كنار TextBox مربوطه نمايش داده می شود . مكان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو اين كه خطائی اتفاق نيافتد ) . در صورتی كه مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مكانی برای نمايش پيام خطاء رزو نخواهد شد و بطور پويا و همزمان با بروز خطاء ايجاد می گردد .
• مقدار ورودی می تواند با يك مقدار مشخص شده توسط خصلت ValueToCompare و يا مقدار يك كنترل ديگر موجود در صفحه ( مشخص شده توسط خصلت ControlToCompare ) ، مقايسه گردد . به صورت پيش فرض ، عمليات مقايسه برای "برابری " انجام خواهد شد . در صورت نياز می توان از ساير عملگرهای مقايسه ای كه توسط خصلت Operator مشخص می گردند ، استفاده نمود . عمليات مقايسه بر اساس نوع داده درج شده در Textbox كه توسط خصلت Type مشخص می گردد ، انجام خواهد شد .
• خصلت Type : در صورتی كه نوع داده ورودی مشخص نگردد ، نوع آن به صورت پيش فرض string در نظر گرفته خواهد شد . يك TextBox خالی ، به عنوان يك نوع داده معتبر ارزيابی خواهد شد . بنابراين ، لازم است كه به همراه كنترل <asp:CompareValidator> از يك كنترل RequiredFieldValidator نيز استفاده گردد تا اين اطمينان حاصل شود كه با عدم درج داده در TextBox مربوطه با آْن به عنوان يك داده معتبر برخورد نخواهد شد .
مثال
در اين مثال ، كاربر می بايست يك عدد مثبت را وارد نمايد و در صورتی كه مقدار ورودی منفی باشد يك پيام خطاء نمايش داده می شود . به همراه كنترل CompareValidator از يك كنترل RequiredFieldValidator نيز استفاده شده است تا عدم درج داده ( خالیبودن ) به عنوان يك داده معتبر ارزيابی نگردد .
مقدار ورودی می بايست از نوع اعشاری (Type=Double ) و بزرگتر از (Operator=GreaterThan ) صفر (ValueToCompare=0 ) باشد تا به عنوان يك داده معتبر ارزيابی گردد .
<SCRIPT Runat="Server"> |
كنترل <asp:CustomValidator>
شكل عمومی
<asp:CustomValidatorid="id" Runat="Server" |
توضيحات
• يك TextBox خالی به عنوان يك داده معتبر در نظر گرفته خواهد شد . بنابراين می بايست به همراه كنترل CustomValidator از يك كنترل RequiredFieldValidator نيز استفاده گردد تا عدم درج داده به عنوان يك داده معتبر ارزيابی نگردد .
• برنامه فرعی صدا زده شده دارای آرگومان های خاص ServerValidateArgs می باشد . در صورتی كه بررسی و ارزيابی صحت داده ورودی توام با موفقيت نباشد ، مقدار خصلت IsValid معادل false خواهد شد . از آرگومان Value ، به عنوان مرجعی به منظور مراجعه به مقدار TextBox ( كنترل مشخص شده توسط خصلت ControlToValidate ) استفاده می گردد .
• خصلت ErrorMessage ، پيام مورد نظر در صورت بروز خطاء را مشخص می نمايد .
• خصلت SetFocusOnErrorMessage ، يك blinking cursor را در كنترل TextBox مربوطه به منظور تسهيل در امر درج داده جديد قرار می دهد .
• خصلت ValidationGroup يك گروه از كنترل های TextBox را كه مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نمايد (در مواردی كه دكمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .
• خصلت Display : كنترل <asp:CustomValidator> ، يك فضای افقی را متناسب با طول رشته مربوط به پيام خطاء اشغال خواهد كرد . در اغلب موارد ، پيام خطاء در كنار TextBox مربوطه نمايش داده می شود . مكان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو اين كه خطائی اتفاق نيافتد ) . در صورتی كه مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مكانی برای نمايش پيام خطاء رزو نخواهد شد و بطور پويا و همزمان با بروز خطاء ايجاد می گردد .
مثال
در اين مثال به منظور ارزيابی و تست داده ورودی در يك TextBox از دو كنترل CustomValidator و RequiredFieldValidator استفاده شده است . داده ورودی می بايست يك عدد صحيح بين صفر تا نود و نه باشد .
پس از كليك بر روی دكمه Submit ، روتين Get_Data فعال و قبل از هر چيز عمليات بررسی و ارزيابی صحت داده ورودی انجام خواهد شد . كنترل RequiredFieldValidator در ابتدا بررسی لازم در خصوص درج داده در TextBox را انجام و در ادامه روتين Validate_TextBox توسط خصلت OnServerValidate كنترل CustomValidator فراخوانده می شود . روتين فوق ، تست های لازم را بر روی داده ورودی انجام خواهد داد ( برای مراجعه به داده ورودی از Args.Value استفاده شده است ) . در صورتی كه هر يك از تست های انجام شده توام با موفقيت نباشد ، خصلت Args.Isvalid مقدار false را خواهد گرفت ( داده ورودی می بايست يك عدد مثبت بين صفر تا نود و نه باشد ) .
پس از انجام فرآيند بررسی داده ورودی ، روتين Get_Data ، اجرا خواهد شد . روتين فوق در ابتدا و پس از كليك بر روی دكمه button فراخوانده می گردد و اجرای آن تا زمانی كه عمليات بررسی و ارزيابی داده ورودی به اتمام نرسيده باشد ، به تاخير خواهد افتاد . پردازش های انجام شده در روتين Get_Data مشروط به انجام موفقيت آميز تست ارزيابی و صحت داده است . بنابراين ، همه چيز وابسته به شرط Page.IsValid شده است و در صورتی كه Args.IsValid معادل false شده باشد ، مقدار Page.IsValid نيز false خواهد شد.
<SCRIPT Runat="Server"> |
گروه های validation
مثال
در فرم ورود اطلاعات زير از چندين كنترل ( چهار كنترل TextBox ) استفاده شده است كه تمامی آنها عضوء يك گروه validation می باشند . پس از كليك بر روی دكمه "ارسال اطلاعات " ، صرفا" آندسته از كنترل هائی كه كنترل های validation آنها عضوء گروه مشخص شده می باشند ، validate خواهند شد .
فرم ورود اطلاعات : استفاده از چهار كنترل TextBox كه تمامی آنها عضوء يك گروه Validation می باشند
<SCRIPT Runat="Server"> |
به دكمه "ارسال اطلاعات " ، يك نام گروه validation نسبت داده شده است تا پس از كليك بر روی آن ، كنترل هائی كه كنترل های validation آنها عضوء گروهی با همين نام می باشند ، بررسی و ارزيابی گردند . در صورتی كه از كنترل های validation ديگر بر روی فرم استفاده شده است كه عضوء گروه validation نمی باشند ، پس از كليك بر روی دكمه "ارسال اطلاعات " ، ارزيابی نخواهند شد .
پس از كليك بر روی هر button موجود بر روی يك فرم ، صرفا" آندسته از كنترل هائی بررسی و ارزيابی خواهند شد كه تشكيل يك گروه را می دهند و از يك نام مشابه برای گروه استفاده می نمايند كه همانند نام نسبت داده شده به button مورد نظر است .
كنترل <asp:ValidationSummary>
شكل عمومی
<asp:ValidationSummaryid="id" Runat="Server" |
توضيحات
• مكان نمايش گزارش پيام های خطاء در محلی است كه كنترل ValidatiomSummary استفاده شده است .
• با استفاده از خصلت ShowMessageBox و نسبت دادن مقدار True به آن ، يك پيام pop-up نمايش داده خواهد شد . بدين ترتيب ، خروجی كنترل ValidationSummary در يك PoP-Up نمايش داده می شود .
• در صورتی كه خلاصه گزارش خطاء مرتبط با يك گروه validation خاص می باشد ، می بايست نام آن گروه به خصلت ValidationGroup نسبت داده شود .
مثال
مثال زير ، بازنويسی مثال قبل است . با اين تفاوت كه در مقابل نمايش جداگانه پيام های خطاء ، از يك كنترل ValidationSummary استفاده شده است .
استفاده از كنترل ValidationSummary
<SCRIPT Runat="Server"> |
تهديدات امنيتی در صورت عدم ارزيابی داده ورودی
تعداد زيادی از برنامه های وب صرفا" از مكانيزم های سمت سرويس گيرنده به منظور بررسی و ارزيابی داده ورودی استفاده می نمايند . مهاجمان با استفاده از روش های متفاوتی می توانند مكانيزم های استفاده شده به منظور ارزيابی داده ورودی را ناديده گرفته و برنامه های وب را در مقابل داده ورودی مخرب خلع سلاح نمايند . مهاجمان ، بدين منظور می توانند با استفاده از ابزارهائی نظير telnet درخواست های HTTP را توليد نمايند . بديهی است در چنين مواردی نبايد انتظار داشت آنان واكنش هائی را كه مد نظر پياده كنندگان برنامه های وب در سمت سرويس گيرنده است ، انجام دهند . با اين كه بررسی و ارزيابی داده ورودی در سمت سرويس گيرنده يك ايده عالی است و می تواند به عنوان يك اقدام مناسب در جهت افزايش كارآئی برنامه های وب تلقی گردد ولی قطعا" رويكرد فوق دارای مزيت امنيتی خاصی نخواهد بود .
به منظور ارزيابی داده ورودی می بايست از روش های سمت سرويس دهنده استفاده گردد تا يك لايه دفاعی مناسب به منظور پيشگيری از درج داده مخرب توسط مهاجمان ايجاد گردد . پس از تحقق خواسته فوق ، می توان با دقت اقدام به بهينه سازی روش های استفاده شده به منظور بررسی و ارزيابی داده ورودی در سمت سرويس گيرنده نيز نمود تا ترافيك غيرضروری بر روی سرويس دهنده به حداقل مقدار ممكن برسد .
بررسی يك نمونه
مهاجمان می توانند از طريق TextBox استفاده شده بر روی يك فرم ، كدهای مخربی را به سيستم وارد نمايند كه حذف تمامی بانك اطلاعاتی را به دنبال داشته باشد . با اين كه همواره فرض پياده كنندگان برنامه های وب بر اين است كه از TextBox برای درج داده در سيستم استفاده خواهد شد ، ولی واقعيت اين است كه ممكن است از آنها برای درج كد نيز استفاده گردد . SQL injection يك نمونه از تهديدات موجود در اين زمينه است .
SQL Injection
SQLString = "SELECT * FROM MyTable WHERE MyKey = '" & MyTextBox.Text & "'" |
دستور SELECT ، به صورت پويا از مقدار درج شده در TextBox استفاده می نمايد . ظاهرا" همه چيز درست است و مشكل خاصی وجود نخواهد داشت ولی فرض كنيد كاربری كد SQL زير را در TextBox وارد نمايد :
پس از درج داده فوق در TextBox ، وضعيت query نوشته شده در برنامه به صورت زير خواهد بود :
SELECT * FROM MyTable WHERE MyKey = ' ' ; DROP DATABASE MyDatabase |
در چنين مواردی ، عبارت SQL شامل دو دستور مجزاء می گردد كه اولين دستور آن با توجه به ماهيت داده ورودی مقدار null خواهد بود و عملا" ركوردی را برنمی گرداند و دومين عبارت SQL ، باعث حذف يك بانك اطلاعاتی خواهد شد . بدين ترتيب يك SQL injection محقق می گردد و كد مخرب با داده مورد انتظار در عبارت SQL جايگزين می شود. با اين كه در يك بانك اطلاعاتی اكسس ، نمی توان چندين عبارت SQL را در يك خط استفاده نمود ولی برخی از سيستم های مديريت بانك های اطلاعاتی قادر به اجراء كد فوق خواهند بود .
پياده كنندگان برنامه های وب می توانند از كنترل های validation به منظور بلاك نمودن اينچنين كدهائی استفاده نمايند . بدين منظور می توان طول رشته ورودی ، نوع داده ورودی و يا وجود داده ورودی در يك محدوده خاص را بررسی نمود . تست های فوق در مواردی كه داده ورودی از نوع string و با طول نامشخص باشند ، كارساز نبوده و نمی توان از كنترل های اشاره شده در جهت ايجاد يك سطح حفاظتی مناسب استفاده نمود .
راه حل چيست ؟
در كد زير از يك عبارت SELECT به منظور بازيابی ركوردهائی خاص از جدول Books در بانك اطلاعاتی BooksDB استفاده شده است . عبارت SQL به عنوان خصلت SelectCommand كنترل منبع داده AccessDataSource ( با " id="BookSource ) در نظر گرفته شده است .
Sub Get_Record (Src As Object, Args As EventArgs) |
يك پارامتر با استفاده از نام خود كه به دنبال يك كاراكتر "@" می آيد ( در اين مثال BookID @ ) ، مشخص می گردد و يك مرجع به داده ورودی است كه در عبارت SELECT و به منظور بازيابی ركوردهای مورد نظر استفاده می گردد . فرض كنيد ، كاربر داده زير را در TextBox وارد نمايد :
Book ID : |
مقدار ورودی در TextBox ، به عنوان مقدار پارامتر BookID @ در عبارت SELECT در نظر گرفته می شود . در چنين مواردی ، می بايست با صراحت مقدار درج شده در TextBox را با پارامتر فوق مرتبط نمود . زمانی كه از كنترل AccessDataSource به منظور بازيابی داده از يك بانك اطلاعاتی استفاده می گردد ، برای مشخص كردن پارامترهای مورد نياز در يك عبارت SELECT ، می بايست از بخش <SelectParameters> در كنترل استفاده گردد . در اين بخش می توان از يك و يا چندين كنترل <asp:ControlParameter> استفاده نمود . با استفاده از كنترل <asp:ControlParameter> ، می بايست يك نام را برای پارامتر در نظر گرفت .همچنين ، لازم است كنترلی كه قرار است مقدار آن به عنوان پارامتر در نظر گرفته شود نيز مشخص گردد.
كد زير نحوه استفاده از پارامتر BookID @ در كنترل AccessDataSource را نشان می دهد .
Book ID: |
توضيحات :
• خصلت Name ، نام در نظر گرفته شده برای پارامتر را كه از آن در عبارت SELECT استفاده خواهد شد را مشخص می نمايد .
• خصلت ControlID ، شناسه (id ) كنترلی است كه داده مورد نياز برای پارامتر را مشخص می نمايد .
• PropertyName ، خصلت كنترلی است كه از مقدار آن به عنوان مرجع استفاده می گردد ( در اين مثال خصلت Text مربوط به كنترل TextBox ) .
• در مثال فوق از يك پارامتر در عبارت SELECT استفاده شده است ، بنابراين به يك كنترل <asp:ControlParameter> نياز می باشد. در صورتی كه لازم است از چندين پارامتر استفاده شود ، می بايست برای هر يك از آنها از يك كنترل <asp:ControlParameter> استفاده گردد .
سادگی كد نويسی
كد زير يك نمونه عبارت SQL را نشان می دهد كه در آن از يك رشته متصل شده به هم استفاده شده است :
SQLString = "SELECT * FROM Books WHERE " & _ |
كد فوق را می توان با عبارت زير جايگزين نمود :
SQLString = SELECT * FROM Books WHERE " & _ |