مقدمه
با قراردادن کدهای ASP درون component های server side ، برنامه نویس نه تنها می تواند از قابلیت های ویژوال بیسیک در نوشتن کدهای خود استفاده کند بلکه سرعت load صفحات ASP وی نیز افزایش می یابد . همچنین این روش راهکاری برای کپسوله سازی و حفاظت از کدهای ASP می باشد .
در این درس یک نمونه اکتیویکس server-side را توسط ویژوال بیسیک ایجاد نموده و از آن در صفحات ASP استفاده خواهیم کرد .
اجزای Server-Side
اکتیوکس های server-side بر خلاف اکتیوکس های clict-side بر روی سرور وب اجرا می شوند و بنابراین بایستی وب سرور مورد استفاده با این تکنولوژی سازگار باشد . زمانیکه وب سرور دستوری را برای پردازش یکسری اطلاعات درون یک صفحه ASP دریافت می کند دستوراتی که درون تگهای <%%>قرار دارند بررسی می شوند . با استفاده از ویژوال بیسیک می توان یک اکتیوکس dll ساخت که جایگزین این کدهای ASP شود . در اینصورت تنها کافیست یک شی از کلاسهای موجود در این dll ساخته شود تا بتوان از قابلیتهای آن استفاده نمود .
ایجاد ActiveX Dll در ویژوال بیسیک
برای ساخت یک اکتیواکس ویژوال بیسیک را اجرا کرده و توسط گزینه New Project پروژه ای از نوع ActiveX Dll ایجاد کنید . پس از اینکه شما روی آیکون ActiveX dll کلیک کنید ویژوال بیسیک پروژه ای پیش فرض بهمراه ی: کلاس خالی برای شما ایجاد می کند . می توانید هم نام پروژه و هم نام کلاس را تغییر دهید همچنین می توانید کلاسهای دیگری به پروژه اضافه کنید .
حال برای اینکه بتوان دستورات ASP را استفاده نموده بایستی از منوی Project وارد بخش References شده و مورد Microsoft Active Server Pages Object Library را انتخاب کنید .
استفاده از متدهای ASP در کلاس های ActiveX
بمنظور استفاده از متدهای ASP در کلاسهای ActiveX بایستی ابتدا روتینی به اسم OnStartPage در داخل کلاس تعریف کنید . ساختار این روتین بصورت زیر است :
Public Sub OnStartPage(PassedScriptingContext As ScriptingContext)x
End Sub
زمانیکه کاربر یک صفحه ASP را که شامل شی ای از کلاس ما باشد فراخوانی کند IIS ، SciptingContext را به شی ما پاس می دهد . ScriptingContext حاوی تمام متدها و خصوصیات ASP می باشد که برای استفاده در دسترس هستند . حال بایستی در روتین OnStartPage تمام اشیای ASP که توسط ScriptingContext در دسترس هستند را به اشیایی از همان نوع assign کنیم تا در صورت لزوم بتوانیم از آنها استفاده نمائیم . بنابراین قبل از نوشتن روتین OnStartPage متغیرهای زیر را تعریف می کنیم :
Private MyScriptingContext As ScriptingContext
Private MyApplication As Application
Private MyRequest As Request
Private MyResponse as Response
Private MyServer As Server
Private MySession As Session
حال در روتین OnStartPage بایستی اشیا فوق را مقداردهی کنید :
Public Sub OnStartPage(PassedScriptingContext As ScriptingContext)x
Set MyScriptingContext=PassedScriptingContext
Set MyApplication=MyScriptingContext.Application
Set MyRequest=MyScriptingContext.Request
Set MyResponse=MyScriptingContext.Response
Set MyServer=MyScriptingContext.Server
Set MySession=MyScriptingContext.Session
End Sub
از تمام اشیا فوق مشابه نوشتن صفحات ASP می توانیم در متدهایی که برای کلاس می نویسیم استفاده کنیم . برای مثال کد ASP زیر را در نظر بگیرید :
<%
MyTempVar=Request.Form(“username”)x
Response.Write(“You Entered : “ & MyTempVar)x
%>
حال فرض کنید می خواهیم همین دستورات را در یک متد از کلاس بنویسیم :
Public Sub MyMethod()x
Dim MyTempVar As String
MyTempVar=MyRequest.Form(“username”)x
MyResponse.Write(“You Entered : “ & MyTempVar)x
End Sub
نکته دیگری که باید در نظر داشت نوشتن روتینی است که در زمان پایان کار با شی فراخوانی می شود . این روتین OnEndPage نام دارد و در آن اشیایی که در روتین OnStartPage مقداردهی کرده ایم را آزاد می کنیم :
Public Sub OnEndPage()x
Set MyScriptingContext=Nothing
Set MyApplication= Nothing
Set MyRequest= Nothing
Set MyResponse= Nothing
Set MyServer= Nothing
Set MySession= Nothing
End Sub
پس از نوشتن متدهای موردنظرتان پروژه را ذخیره کنید . حال برای کامپایل پروژه از منوی File مورد File/Make Dll را انتخاب نمائید تا پروژه کامپایل شده و فایل dll موردنظرتان ساخته شود . این فایل را در دایرکتوریی که صفحات ASP شما در آنجا قرار دارد کپی کنید .
نکته ای که باید مورد توجه قرار داد اینست که در صورتیکه می خواهید از این dll در سیستم دیگری استفاده کنید ابتدا بایستی آنرا رجیستر کنید . برای رجیستر کردن یک dll از برنامه regsvr32.exe موجود در دایرکتوری سیستم ویندوز استفاده می شود :
Regsvr32.exe C:\InetPub\wwwroot\Example\Example.dll
استفاده از ActiveX Dll در صفحات ASP
برای استفاده از کلاس نوشته شده در فایل dll در صفحات ASP ابتدا بایستی یک شی از آن کلاس ایجاد کنیم :
<%
Set ObjRefrence = Server.CreateObject(“ProjectName.ClassName”)x
%>
پس از ساخت شی می توانیم از متدهای موجود در کلاس استفاده کنیم
———————————-
+COM چیست ؟
روشی که برای دسترسی به Object های ASP در درس گذشته بیان شد تا IIS 3.0 استفاده می شد . این روش استفاده از متدهای OnStart و OnEnd بود . البته گرچه هنوز این روش از سوی IIS ورژن ۵ پشتیبانی می شود اما دارای یک مشکل است :
اگر بخواهید از یک کلاس در کلاس دیگری استفاده کنید نمی توانید در کلاس مورد استفاده ، دو متد ذکر شده را قرار دهید و بنابراین به اشیای ASP دسترسی نخواهید داشت .
راه حلی که برای این مشکل ارائه شد تکنولوژی +COM می باشد .
بطور خلاصه در این تکنولوژی شیی به اسم ObjectContext وجود دارد که از طریق آن می توانید به اشیای ASP دسترسی داشته باشید .
برای استفاده از تکنولوژی +COM ابتدا از منوی Project ، References را انتخاب کرده و مورد زیر را انتخاب کنید :
COM+ Services Type Library
سپس در کلاسهای خود متغیرهای زیر را تعریف کنید :
Dim Request As ASPTypeLibrary.Request
Dim Response As ASPTypeLibrary.Response
Dim Server As ASPTypeLibrary.Server
Dim Session As ASPTypeLibrary.Session
Dim Application As ASPTypeLibrary.Application
حال در متد Initialize هر کلاس بایستی شی ObjectContext را تعریف کرده و مقداردهی کنید . سپس متغیرهای بالا را با استفاده از این شی مقداردهی نمائید :
Private Sub Class_Initialize()x
Dim objCtx As ObjectContext
Set objCtx = GetObjectContext
Set Request = objCtx.item(“Request”)x
Set Response = objCtx.item(“Response”)x
Set Server = objCtx.item(“Server”)x
Set Session = objCtx.item(“Session”)x
Set Application = objCtx.item(“Application”)x
End Sub
+ موضوع درس بعد : دسترسی به Database در کلاسهای اکتیوایکس Server-Side
پاسخ به سوالات شما :
۱ – چه جوری دکمه ها و لیست باکس ها در ویژوال بیسیک را شکل اکس پی کنیم؟اصلان می شه؟
پاسخ : ؟؟؟؟
۲ – تویه vb چطوری میشه فایله اجراییdllهاشو نخاد و بدونه اونا اجرا بشه ؟
پاسخ : برنامه های اجرایی ویژوال بیسیک برای اجرا شدن به یکسری فایلهای دیگه نیاز دارند مثلاً Vb Runtime Dll . برای اینکه به این فایلها نیازی نباشد بایستی یک برنامه نصب setup file برای پروژه تان بسازید تا بتوان برنامه را روی هر کامپیوتری نصب و اجرا کرد . ساده تری راه استفاده از ابزار Package & Deployment موجود در ویژوال استدیو است . ابزارهای حرفه ای تر عبارتند از : InstallShield ، InstallWise ، Setup Factory و …
۳ – اگه ممکنه یه توضیحی درباره ی دی کد کردن دی ال ال mpr دهید .
پاسخ : ؟؟؟؟
۴ – چطوری میشه تو یه تکس باکس در ویژوال بیسیک فرمان داد اینتر شود یعنی به خط بعدی رود؟ ( یعنی زمانی که مولتی لاین است)
پاسخ : استفاده از کاراکتر vbCrLf
۵ – من می خوام با زبانهایی PHP و ASP برنامه بنویسیم ولی تمامی این زبانها Server_side هستند و من باید روی سرور این کار ها رو انجام بدم من می خوامم بدونم که چه طوری می تونم کامپیوتر خودمو وب سرور کنم البته یه چیزهای می دونم که باید IIS رو نصب کنم ولی نه به طور کامل خواهش می کنم کمکم کنید
پاسخ : بایستی ویندوز ۲۰۰۰ یا XP نصب کرده و از IIS آنها استفاده کنید . البته در ویندوزز ۲۰۰۰ IIS بطور اتوماتیک نصب نمی شود و باید آنرا خودتان اضافه کنید . برای اطلاعات بیشتر در مورد کار با IIS به کتاب ها و مراجع اینترنتی مراجعه کنید مراجعه کنید .
———————————
خلاصه ای بر چگونگی کار با بانک های اطلاعاتی ( Database ) در وی بی :
+ برای آشنایی کامل با چگونگی کار با بانک های اطلاعاتی در ویژوال بیسیک و بطور کلی Database Programming به کتاب برنامه نویسی بانک های اطلاعاتی در ویژوال بیسیک انتشارات نص رجوع کنید .
قبل از اینکه چگونگی نوشتن یک کلاس Database برای استفاده در ASP را آموزش دهم ، مقدمه ای بر چگونگی کار با بانک های اطلاعاتی در وی بی را شروع می کنم .
برای کار با بانک های اطلاعاتی در ویژوال بیسیک روشها و امکانات مختلفی وجود دارد که یکی از بهترین آنها استفاده از تکنولوژی ( ADO ( ActiveX Data Object می باشد . بدون هیچ توضیحی در مورد ساختار این تکنولوژی و نیز سایر روشهای دیگر ، به سراغ روش استفاده از این تکنولوژی می روم :
- برای کار با ADODB ابتدا بایستی از Reference ها مورد Microsoft ActiveX Data Object را انتخاب کرد .
- قدم بعد تعریف یک شی ADO Connection برای اتصال به بانک اطلاعاتی است :
Dim cn As ADODB.Connection
- سپس بایستی این شی ADO Connection را ایجاد نمود :
Set cn = New ADODB.Connection
- همچنین بایستی یک شی ADO Recordset برای گرفتن مجموعه ای از رکوردهای بانک اطلاعاتی تعریف کرد :
Dim rs As ADODB.Recordset
- حال بایستی اتصال به بانک اطلاعاتی را باز نمود . در این مرحله با توجه به نوع بانک اطلاعاتی و اتصالی که می خواهیم داشته باشیم عبارت اتصال ممکن است متفاوت باشد . فرض کنیم عبارت اتصال را در یک متغیر نوع String به اسم ConnString قرار دهیم :
• در صورتی که بانک اطلاعاتی مقصد SQL Server باشد و بخواهیم بطور مستقیم و بدون استفاده از واسط ODBC به آن متصل شویم :
ConnString=”Provider=SQLOLEDB.1;Password=yourpassowrd;Persist Security Info=True;User ID=yourusername; Initial Catalog=yourDatabaseName;Data Source=yourServerName”
• در صورتی که بانک اطلاعاتی مقصد SQL Server باشد و بخواهیم با استفاده از واسط ODBC به آن متصل شویم :
ConnString=”Provider=MSDASQL.1;Password=yourpassowrd;Persist Security Info=True;UserID=yourusername;DataSource=yourODBC_DataSourceName;Mode=ReadWrite”
• در صورتی که بانک اطلاعاتی مقصد Access باشد :
ConnString=” Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=yourDatabaseFilePath;Persist Security Info=False”
حال بایستی این اتصال را باز نمود :
cn.Open(ConnString)x
- قدم بعدی ایجاد شی ADO Recordset می باشد :
Set rs = New ADODB.Recordset
- سپس بایستی با توجه به کاری که می خواهیم با جداول آن بانک اطلاعاتی انجام دهیم یک sql query را توسط شی Recordset به آن بفرستیم :
rs.Open yourSQLquery,cn,OpenKeyset, adLockOptimistic
بعبارت دیگر نوع باز کردن Recordset متفاوت است و توسط query مورد نظر مشخص می شود برای مثال برای انتخاب فیلدهای یک Table :
SELECT DISTINCT yourfields from yourtable WHERE yourcondition
نکته : نوع قفل کردن مجموعه رکورد می تواند adLockReadOnly نیز باشد .
- حال با استفاده از این Recordset می توان یکسری کار را روی رکوردهای موجود در جداول انجام داد برای مثال :
۱ – حرکت به ابتدای مجموعه رکورد :
rs.MoveFirst
۲ – حرکت در طول مجموعه رکورد :
Do
tmp = rs.fields(0)x
.
.
.
rs.MoveNext
Loop Until (rs.EOF)x
3 – بستن مجموعه رکورد و بستن اتصال به بانک اطلاعاتی :
rs.Close
cn.Close
4 – حذف رکورد جاری از مجموعه رکورد :
rs.delete
5 – ایجاد رکورد جدید در مجموعه رکورد :
Dim fields(RecordsetFieldsCount) As Variant
Dim values(RecordsetFieldsCount) As Variant
fields(0) = Field 1 Name
fields(1) = Field 2 Name
.
.
.
fields(n) = Field n Name
values(0) = Field 1 Value
values(1) = Field 2 Value
.
.
.
values(n)= Field n Value
rs.AddNew fields, values
rs.update
————————-
آشنایی با چند query برای کار با جداول بانک های اطلاعاتی
۱- SELECT : برای انتخاب رکوردها از یک جدول استفاده می شود . فرمت کلی این دستور بصورت زیر است :
SELECT fieldnames FROM tablename WHERE condition ORDER BY fieldnames
مثال : فرض کنید یک جدول به اسم mytable داریم که دارای دو فیلد به نامهای id از نوع integer و name از نوع string باشد :
– انتخاب تمامی رکوردهای جدول :
query=”Select * from mytable”x
- انتخاب فیلد name تمام رکوردهای جدول :
query=”Select name from mytable”x
- انتخاب رکوردهایی از جدول که فیلد id آنها برابر ۲ باشد :
query=”Select * from mytable where id=2″x
- انتخاب رکوردهایی از جدول که فیلد name آنها برابر a باشد :
query=”Select * from mytable where name=’a’”x
توجه داشته باشید که چون فیلد name از نوع string است در دستور فوق از ‘ برای مقدار فیلد name استفاده شده است .
- انتخاب رکوردهایی از جدول که فیلد id آنها برابر ۲ و فیلد name آنها برابر a باشد و بر حسب id مرتب شده باشند .
query=”Select * from mytable where id=2 and name=’a’ order by id”x
نکته : در صورتیکه بخواهیم از یک متغیر برای مقداردهی به یک فیلد در query استفاده کنید با توجه به اینکه آن متغیر از نوع integer و یا string است باید بصورت زیر عمل کنیم :
Dim mId as integer
Dim mName as string
mId=1
mName=”a”x
query=”Select * from mytable where id=” & str(mId) & ” and name=’” & mName & “’”x
2 – INSERT : این دستور برای قرار دادن یک رکورد در جدول استفاده می شود . فرمت کلی این دستور بصورت زیر است :
INSERT INTO tablename (field1name,field2name,…) VALUES (field1value,field2value,…)x
مثال :
query=”Insert into mytable (id,name) values (1,’a’)”x
3 – UPDATE : این دستور برای تغییر مقادیر یک رکورد از جدول استفاده می شود . فرمت کلی این دستور بصورت زیر است :
UPDATE tablename SET field1name=field1value, field2name=field2value,…
مثال :
query=”Update mytable set id=2 , name=’b’”x
4 – DELETE : این دستور برای حذف یک یا چند رکورد از جدول استفاده می شود . فرمت کلی این دستور بصورت زیر است :
DELETE FROM tablename WHERE condition
مثال :
query=”Delete from mytable where id=1″x
حال که با تکنولوژی ADODB و نیز query های مختلف برای کار با جداول بانک های اطلاعاتی آشنا شدید می توانیم کلاسی برای کار با بانک های اطلاعاتی بنویسیم و از آن در صفحات asp استفاده کنیم اما همانطور که در قسمت قبل دیدید برای اتصال به یک بانک اطلاعاتی نیاز به یکسری اطلاعات مثل نام سرور ، نام بانک اطلاعاتی و … داریم . چند روش برای دادن این اطلاعات وجود دارد :
۱ – در کلاسی که می نویسیم این مقادیر را مشخص کنیم . اشکال این روش اینست که از کلاس نوشته شده تنها برای یک کاربرد خاص می توانیم استفاده کنیم و در صورتیکه سرور بانک اطلاعاتی و یا نام بانک اطلاعاتی ویا username و password اتصال تغییر کند بایستی در کلاس نوشته شده نیز تغییرات را اعمال کرده و مجدداً آنرا کامپایل کنیم .
۲ – راه حل دوم اینست که پارامترها را از طریق asp به متد اتصال موجود در کلاس بفرستیم برای مثال :
Set db=server.createobject(“dbclass.database)x
Db.connect(servername,databasename,username,password)x
که coonect متد اتصال به بانک اطلاعاتی در کلاس database می باشد .
۳ – روش سوم آنست که این پارامترها را در یک فایل XML قراردهیم و در متد connect آنها را از فایل بخوانیم . مزیت این روش اینست که پارامترها هم به آسانی قابل تغییر بوده و هم براحتی آنها می توان آنها را استخراج نمود .
برای این منظور بایستی ابتدا یک کلاس برای خواندن اطلاعات از فایل xml بنویسیم که موضوع درس بعد می باشد .
نکته : در صورتیکه با فرمت فایلهای xml آشنا نیستید پیشنهاد می کنم یک مطالعه مقدماتی در این زمینه انجام دهید .
———————-
نوشتن کلاس Database – بخش اول :
پس از مباحثی که در مورد شی ADODB و چگونگی استفاده از آن در وی بی و نیز استفاده از فایلهای XML داشتیم اکنون می توانیم یک کلاس کامل و قدرتمند برای کار با بانکهای اطلاعاتی در ASP بنویسیم .
مراحل کار بصورت زیر می باشد :
۱ – ابتدا یک پروژه از نوع ActiveX Dll ایجاد کنید و نام آنرا DBase بگذارید .
۲ – از بخش References مواردی را که در مباحث قبلی گفته شد به پروژه اضافه کنید .
۳ – متغیر Cn را برای کلاس بصورت زیر تعریف کنید :
Private Cn As ADODB.Connection
۴ – ابتدا یک متد به اسم InitialConnection برای کلاس می نویسیم . در این متد ابتدا پارامترهای اتصال به بانک اطلاعاتی را مشابه آنچه در درس قبل گفته شد از یک فایل XML به اسم config.xml می خوانیم و با استفاده از آنها اتصال به بانک اطلاعاتی را باز می کنیم :
Public Sub InitialConnection()x
Dim userName, Password, database_name, server_name
Dim xmlf As NewXMLReader
Call xmlf.Initiate(“config.xml”)x
userName = xmlf.getvalue(“DataBaseID”) x
Password = xmlf.getvalue(“DataBasePassword”) x
database_name = xmlf.getvalue(“DataBaseName”) x
server_name = xmlf.getvalue(“ServerAddress”)x
Set Cn = CreateObject(“ADODB.Connection”)x
Cn.ConnectionString = “Provider=SQLOLEDB.1;Password=” & Password & “;Persist Security Info=True;User ID=” & userName & “;Initial Catalog=” & database_name & “;Data Source=” & server_name
Cn.Mode = adModeReadWrite
Cn.Open
End Sub
لازم به ذکر است که XMLReader کلاس کار با فایلهای XML است که در قسمت قبلی در مورد آن صحبت کردیم .
۵ – برای بستن اتصال متد زیر را به کلاس اضافه کنید :
Public Sub EndConnection()x
Cn.Close
Set Cn = Nothing
End Sub
6 – برای اجرای query هایی که نتیجه آنها از نوع Boolean است ( مثل Insert و Delete ) متدی به اسم ExecuteUpdate را به کلاس اضافه کنید :
Public Function ExecuteUpdate(ByVal squery As String) As Boolean
Dim myrs As New Recordset
If Not (makesInjection(squery)) Then
myrs.LockType = adLockOptimistic
Set myrs = Cn.Execute(squery) x
ExecuteUpdate = True
Exit Function
Else
ExecuteUpdate = False
Exit Function
End If
End Function
6 – برای اجرای query هایی که نتیجه آنها از نوع RecordSet است ( مثل Select ) متدی به اسم ExecuteQuery را به کلاس اضافه کنید :
Public Function ExecuteQuery(ByVal squery As String) As Recordset
If Not (makesInjection(squery)) Then
Set ExecuteQuery = Cn.Execute(squery)x
Exit Function
Else
Set ExecuteQuery = Nothing
Exit Function
End If
End Function
همانطور که می بینید در دو متد ExecuteUpdate و ExecuteQuery از تابعی به اسم makesInjection استفاده شده است . این تابع بررسی می کند که آیا در query ورودی SQL-Injection وجود دارد یا نه .
- این تابع موضوع قسمت بعدی این سلسله مباحث می باشد .
————————————————
نوشتن کلاس Database : بخش دوم
sql-injection چیست ؟
همانطور که می دانید در اغلب برنامه های کاربردی تحت وب از بانکهای اطلاعاتی استفاده می شود . این برنامه ها داده های ورودی کاربر را از طریق فرمهای html دریافت کرده و بر اساس آن یک query تولید کرده و آنرا به بانک اطلاعاتی ارسال می کنند . در واقع ارتباط بین برنامه تحت وب با بانک اطلاعاتی بر اساس تولید query از داده های کاربر برقرار می شود . اکثر این برنامه ها از زبان SQL برای این ارتباط استفاده می کنند . اما نکته ای که در این بین وجود دارد اینست که تولید query بر اساس داده هایی که کاربر مستقیماً در فیلدهای ورودی صفحه وب وارد کرده می تواند خطرناک باشد . بعبارت دیگر اگر برنامه محتویات یک فیلد را که توسط کاربر وارد شده در جلوی یک دستور SQL بچسباند و آنرا جهت اجرا روی بانک اطلاعاتی بفرستد در اینصورت یک هکر ماهر که با زبان SQL آشنا باشد می تواند محتویات این فیلدها را طوری با دستورات SQL پر کند و چون ای داده ها مستقیماً برای تولید query استفاده می شود ممکنست آن query تبدیل به یک فرمان مخرب شده و پس از اجرا ، اهداف نفوذگر را برآورده نماید .
مثال : فرض کنید دو فیلد به اسمهای username و password در یک فرم وب قرار دارد که برای ورود به یک سایت استفاده می شود . همچنین فرض کنید از اطلاعات این فیلدها بطور مستقیم یک query بصورت زیر برای بانک اطلاعاتی ارسال شود :
us=request.form(“username”)
psw=request.form(“password”)
query=”SELECT * FROM Users WHERE username=’”&us&”‘ AND password=’”&psw&”‘”
حال در صورتیکه هکر یک username صحیح ( مثلاً xxx ) از سیستم را بداند و در فیلد username مقدار صحیح را وارد کرده و در فیلد password عبارت زیر را وارد کند :
۱۱۱۱۱۱۱′ or username=’xxx’
در اینصورت query بصورت زیر در می آید :
SELECT * FROM Users WHERE username=’xxx’ AND password=’111111′ or username=’xxx’
در اینصورت هکر بدون دانستن یک password مجاز می تواند به سیستم وارد شود .
این امر بخاطر آنست که چون فیلدهای وارد شده توسط کاربر بطور مستقیم در query قرار داده شده اند هکر توانسته کاراکتر ‘ را که در زبان SQL یک کاراکتر کنترلی بوده و عملکرد خاصی دارد ( عمل خاتمه دادن به عبارت SQL ) را در در query بگنجاند و سپس با دادن دستورات SQL مناسب کنترل را بدست بگیرد .
این سناریو می تواند بسیار خطرناکتر باشد زیرا هکر می تواند از سایر دستورات SQL مثل INSERT و DELETE نیز استفاده کند .
- در نگارش مطالب فوق از کتاب ” نفوذگری در شبکه و روشهای مقابله با آن ” نوشته مهندس احسان ملکیان استفاده شده است . برای آشنایی بیشتر با sql-injection و روشهای مقابله با آن به صفحات ۳۲۰ تا ۳۲۸ این کتاب مراجعه کنید .
برای مقابله با این حملات بایستی از داده های ارسال شده توسط کاربر مستقیماً query تولید نکنیم بلکه ابتدا عدم وجود کاراکترهای کنترلی مثل ‘ و ” و ; و *و غیره را در آن بررسی کنیم . برنامه ابتدا باید در query وجود چنین کاراکترهایی را در مکانهای غیرمجاز بررسی کند . در بخش بعدی برنامه ای را جهت بررسی query های SQL بمنظور مقابله با sql-injection ارائه خواهم داد .
——————————
تابع بررسی وجود sql-injection که در قسمت قبل در آن صحبت کردیم بصورت زیر است :
Private Function makesInjection(ByVal query As String) As Boolean
Dim specialCharacters() As String
Dim inQoute As Boolean
specialCharacters = “– ;,”
inQoute = False
For i = 1 To Len(query)
Char = Mid(query, i, 1)
If Mid(query, i, 1) = “‘” And inQoute = False Then
inQoute = True
GoTo EndFor
End If
If Mid(query, i, 1) = “‘” And inQoute = True Then
inQoute = False
GoTo EndFor
End If
If inQoute = False Then
For Index = 1 To UBound(specialCharacters)
schar = specialCharacters(Index)
cchar = Mid(query, i, Len(schar))
If schar = cchar Then
Exit For
End If
Next
If Index < UBound(specialCharacters) Then
makesInjection = True
Exit Function
End If
End If
EndFor:
Next
If inQoute = True Then
makesInjection = True
Else
makesInjection = False
End If
End Function
ورودی این تابع query شما و خروجی آن false یاtrue است .
عملکرد تابع بصورت زیر است :
این تابع در طول رشته query شروع به حرکت می کند و هر کاراکتر از آنرا بررسی می نماید . در صورتیکه کاراکتر جاری ‘ باشد و داخل ‘ ’ نباشیم متغیر مربوط به آن true شده و حلقه یکی بجلو می رود . اما در صورتیکه کاراکتر جاری ‘ باشد و داخل ‘ ’ باشیم متغیر مربوط به آن false شده و حلقه یکی بجلو می رود . سرانجام در صورتیکه داخل ‘ ’ نباشیم بررسی می شود که این کاراکتر یکی از کاراکترهای غیر مجاز ( کاراکترهای موجود در رشته specialCharacters ) نباشد که اگر باشد تابع true بر می گرداند .
پس از اتمام حلقه متغیر مربوط به ‘ بررسی می شود که اگر true باشد در صورت injection وجود داسته و تابع نیز true بر می گرداند .
———————–
نکته ای در مورد شی Recordset :
متد ExecuteQuery که در کلاس Database نوشتیم یک رکوردست را بعنوان نتیجه انجام query ورودی روی بانک اطلاعاتی شما برمی گرداند .
همانطور که می دانید توسط خصوصیت RecordCount می توان تعداد رکوردهای نتیجه شده از یک query را که در رکوردست قرار دارند بدست آورد .
اما مشکلی وجود دارد اینست که با روشی که ما در قسمتهای قبل برای اجرای query در این متد استفاده کرده بودیم ( myrs = Cn.Execute query ) نمی توان از خاصیت Recordcount رکوردست استفاده نمود زیرا همیشه ۱- برمی گرداند . بعبارت دیگر در عبارت زیر مقدار count همیشه ۱- خواهد بود :
myrs.execute(query)
count=myrs.RecordCount
برای حل این مشکل بایستی رکوردست را با CursorType مساوی adOpenStatic باز کرد . بعبارت دیگر بجای دستورات فوق از دستور زیر استفاده کنید :
myrs.Open squery, Cn, adOpenStatic, adLockOptimistic
count=myrs.RecordCount
دیدگاه خود را بیان کنید.
باید وارد سایت شده باشید برای دیدگاه دادن