ورود

View Full Version : خواهش می کنم این چند مورد را در برنامه نویسی رعایت کنید



Behrouz_Rad
یک شنبه 29 آذر 1383, 07:49 صبح
سلام.
چند تا نکته هست که اگر دوستان در برنامه هایی که می نویسند رعایت کنند موفق تر خواهند بود.

1) در VB چندین نوع ساختار حلقه تکرار وجود داره که بنا به نیاز از هر کدام از آنها استفاده میشه.
به عنوان مثال: اگر تعداد دفعات تکرار از قبل معلوم باشه از حلقه For و اگر تعداد دفعات تکرار نامعلوم باشه از حلقه های Do While و Do Until و … استفاده میشه.
برخی افراد با اینکه تعداد دفعات تکرار از قبل مشخصه، از حلقه While استفاده می کنند. مثلا بارها دیدم که در برنامه نویسی صفحات وب با ASP کلاسیک که از VBScript استفاده می کنند، برای چاپ مقادیر Recordset از دستورات زیر استفاده میشه: (شبه کد)


Do While Not Rst.EOF
<TD> Rst(0).Value </TD>
Rst.MoveNext
Loop

استفاده از این کد، به مقدار زیادی در پایین آوردن سرعت پردازش و در نتیجه در Load شدن دیر صفحه تاثیر می گذاره.
دلیل: در هر بار اجرای حلقه، شرط جلوی حلقه ی While باید چک شود که این خود زمان گیر است.
پس بهتره به جای حلقه While از حلقه For استفاده کنیم: (شبه کد)


Dim I
For I = 0 To Recordset.RecordCount – 1
<TD> Response.Write Rst(0).Value </TD>
Rst.MoveNext
Next

اگر دقت کنید، می بینید که کد فوق نیز با حلقه While هیچ تفاوتی ندارد، چون که در هر بار اجرای حلقه، مقدار Recordset.RecordCount ب(تعداد رکوردها) باید محاسبه شود. بنابراین کد فوق را به شکل زیر اصلاح می کنیم: (شبه کد)


Dim I , J
J = Recordset.RecordCount – 1
For I = 0 To J
<TD> Response.Write Rst(0).Value </TD>
Rst.MoveNext
Next

استفاده از حلقه For، کاهش زمانی به میزان 33 درصد را در پی خواهد داشت.

2) (شاید بعضیا این مورد رو بدونن!) دستور SQL زیر را در نظر بگیرید:


“Select * From MyTable Where MyField = ‘” & Text1.Text & “’”

این بدترین بلاییه که میشه سر داده ها آورد!!!
حالا فرض کنید که من در TextBox، متن زیر رو تایپ کنم:


& “ Or MyField = ‘’”

مسلمه که با وارد کردن خط فوق در TextBox توسط کاربر، به جای نمایش یک سری اطلاعات با شرط خاص، تمامی اطلاعات نمایش داده خواهند شد.
تعریف: به وارد کردن دستورات SQL توسط کاربر در مکان مورد نظر و پردازش آنها به صورت غیرمجاز توسط DBMS، خطای SQL Injection گفته می شود.
این مورد تقریبا 6 سال پیش توسط آقای Williams در کنفرانسی که در مورد امنیت داده ها در واشنگتن آمریکا برگزار شد، مطرح شد.
راه حل مقابله با این حملات، استفاده از Stored Procedure ها، چه در بانک اطلاعاتی ACCESS و چه در SQL Server است.
البته اگر از بانک SQL Server استفاده می کنید باید برای ایجاد Stored Procedure ها (روال های ذخیره شده)، تا حدودی با T-SQL (Transact SQL) یا SQL تراکنشی که زبان برنامه نویسی مورد استفاده در SQL Server است، آشنایی داشته باشید.

اگر از بانک Access استفاده می کنید، می توانید با ایجاد یک Command و تنظیم خاصیت Parameters و عبور دادن نام فیلد و مقدار آن، این کار را انجام دهید.
اما در SQL Server ابتدا باید Stored Procedure را با دستورات T-SQL بسازید.
به عنوان مثال، کد زیر در Query Analyzer، یک Stored Procedure می سازد.


Create Procedure Test

@username varchar(20),
@password varchar(20)
AS
Select MyField1,MyField2 From MyTable
Where MyField1=@username
And MyField2=@password


3) در تمامی برنامه هایتان بهتر است ابتدا چک کنید که آیا برنامه ی شما قبلا اجرا شده است یا خیر زیرا اجرای دو نسخه ی برنامه در یک زمان ممکن است باعث بروز مشکلاتی در برنامه شما شود.
این کار را می توانید با استفاده از خاصیت PrevInstance که در شی App وجود دارد انجام دهید:


Private Sub Form_Load()
If App.PrevInstance Then
MsgBox "Program is already Running!"
End
End If
End Sub


نکته مهم: حتما دستور End را در صورتی که برنامه قبلا اجرا شده است بنویسید تا از اجرای نسخه دوم، جلوگیری شود.
همچنین می توانید Handle (هندل) برنامه خود را نیز با استفاده از خاصیت hInstance از شی App به دست آورید.


Dim MyHandle As Long
MyHandle = App.hInstance


4) برای استفاده از توابع API نیاز به تعریف آنها ندارید.
همون طور که می دونید، توابع API در فایل های خاصی قرار دارند. به عنوان مثال: User32.dll، Kernel32.dll، tlbinf32، GDI32 ،Shell32 و …
می توانید برای استفاده از توابع موجود در این فایل ها، تنها با دسترسی به آدرس این توابع در این فایل ها، آنها را اجرا کنید.
برای این منظور نیاز به فراخوانی و استفاده از چهار تابع API دارید.


Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long

Public Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long

Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long

Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long



تابع LoadLibrary برای بارگذاری یک فایل DLL یا EXE در حافظه به کار می رود تا از این طریق بتوان به آدرس های توابع موجود در این فایل ها دست پیدا کرد.
به عبارت دیگر باید در آرگومان اول این تابع، نام فایل کتابخانه ای را ذکر کرد که تابع مورد نظر ما در آن وجود دارد.
این تابع تنها یک آرگومان دارد و آن، نام فایل است.
می توانید در این تابع، تنها نام فایل را ذکر کنید (بدون پسوند). در این صورت به طور پیش فرض برای فایل، پسوند DLL در نظر گرفته می شود.


Dim Res As Long
Res = LoadLibrary(“user32”)

پس از پایان کار با تابع API، باید کتابخانه حاوی آن فایل را از حافظه خارج کرد.
این کار با استفاده از تابع FreeLibrary انجام می شود.
این تابع نیز تنها یک آرگومان دارد و آن نیز شماره ای است که با استفاده از تابع LoadLibrary به دست آمده و در متغیر ریخته شده.
به عنوان مثال در مثال قبل، برای حذف آدرس و آزاد کردن فضای تخصیص یافته به پردازه LoadLibrary به شکل زیر عمل می کنیم:


FreeLibrary Res

تابع GetProcAddress به منظور دریافت آدرس تابع مورد نظر که در فایل کتابخانه ای وجود دارد استفاده می شود.
این تابع، دو آرگومان دارد.
آرگومان اول، شماره ی پردازه ی اختصاص یافته به فایل کتابخانه ای است.
آرگومان دوم نیز که از نوع رشته ای (String) است، به نام تابعی که قصد فراخوانی آن را داریم اختصاص دارد.
با توجه به مثال های قبل:


Dim MyVar As Long
MyVar = GetProcAddress(Res , “MessageBox”)

همان طور که ملاحظه می کنید، با خط فوق، تابع MessageBox بدون نیاز به تعریف آن فراخوانی شد.
اما هنوز کار ما به پایان نرسیده. حال باید پارامترهای واقعی را به پارامترهای مجازی مربوط به این تابع، Pass بدهیم.
تابع CallWindowProc برای Pass دادن آرگومان های یک تابع به آن به کار می رود.
اولین آرگومان این تابع به شماره اختصاص یافته به تابع مورد نظر اشاره می کند.
آرگومان های بعدی نیز پارامترهای مرتبط با تابع هستند که به ترتیب، Pass داده می شوند.
مثال زیر، یک مثال کلی از تمام گفته های فوق است.


Private Const MB_OK = &H0&
Private Sub Command1_Click()
On Error Resume Next
Dim Res As Long, MyVar As Long
Res = LoadLibrary("user32")
MyVar = GetProcAddress(Res, " MessageBox")
CallWindowProc MyVar, Me.hWnd, "This is a Test", App.Title, MB_OK
FreeLibrary lb
End Sub



موفق باشید.
بهروز راد
:wink:

ghaum
یک شنبه 29 آذر 1383, 08:10 صبح
:thnx: :تشویق:

Payam Moradi
یک شنبه 29 آذر 1383, 09:29 صبح
سلام
خسته نباشید. خوب بود.
ولی با مورد دوم با اون 6 هفت خط اول مخالفم. در دستورات SQL هر چی بین دو آپستروف '' قرار بگیره فقط و فقط به صورت رشته خونده میشه نه شی یا نام فیلد یا چیز دیگه. مثل اینکه ما بیام دستور ذیل رو بگیم درست نیست:

Text1.Text = "Text2.Text"

موفق باشید :flower:

Behrouz_Rad
یک شنبه 29 آذر 1383, 10:17 صبح
سلام.
شما می دونی SQL Injection چیه؟؟؟
شما می دونی که میشه دستورات SQL رو از طریق تزریق غیرمجاز SQL در برنامه اجرا کرد.
من متوجه منظور شما نشدم.
:گیج:

hmm
یک شنبه 29 آذر 1383, 11:17 صبح
حرف آقای بهروز راد کاملا صحیحه
شما با استفاده از این ضعف میتوانید حتی کل دیتابیس سرور رو down کنید
ویا اگه برنامه نویس شما رو با یک یوزر admin به دیتابیس وصل کرده باشه که کنترل کل سرور رو میتونید در دست بگیرید
این بانگ تقریبا قدیمیه ولی هنوز خیلی از برنامه نویسان از وجود (sql injection) ویا (url injection) بی خبرند
و تقریبا راه حلی جز کنترل ورودی کاربر و یا روشی که آقای راد گقتند نداره :sorry:

Payam Moradi
یک شنبه 29 آذر 1383, 12:53 عصر
سلام


شما می دونی که میشه دستورات SQL رو از طریق تزریق غیرمجاز SQL در برنامه اجرا کرد
من برای اینکه نظر شما و خودم رو بررسی کنم آزمایش کردم (نه مثل بعضی ها که زود قضاوت میکنند در بعضی از تاپیک ها)
ولی هر کار کردم نتونستم از این طریق یک طوری دستورات SQL رو دستکاری کنم که نتیجه دیگه ای غیر از انتظار بده. میشه یک نمونه ارسال کنید یا کامل توضیح بدید.
نکنه این مورد مال موارد خاصی هست که تا حالا برنخوردم. بیشتر اگه میشه توضیح بدید. ممنون میشم.


تقریبا راه حلی جز کنترل ورودی کاربر ...
خب مسلما باید ورودی کاربر رو کنترل کرد که معمولا چون تو ایران حالا همه فیلدها نه ولی اکثر فیلدها فارسی تایپ میشن باید جلوی تایپ انگلیسی رو بگیریم. و یک چیز دیگه که اینکه اطلاعات رو اگه کد کرده باشیم مجبوریم متن Text ها یا متغییرها رو به صورت کد به SQL ارسال کنیم. پس فکر نمیکنم مشکلی خاص پیش بیاد.
اگر موردی هست که شما بهتر میدونید من مشتاقم به شنیدن. (هر دو اساتید)

Behrouz_Rad
یک شنبه 29 آذر 1383, 12:53 عصر
سلام.
نیاز به توضیح من نیست.
در اینجا هر آنچه ک لازم هست جناب نصیری فرمودند.
http://www.barnamenevis.org/forum/viewtopic.php?t=6997&start=0

Take Care My Dear
Behrouz Rad Love You
:wink:

Payam Moradi
یک شنبه 29 آذر 1383, 13:12 عصر
:wink:

بابک زواری
یک شنبه 29 آذر 1383, 15:31 عصر
منم یک مقاله انگلیسی در این مورد دارم که خیلی کامله فقط باید جایی برای upload پیدا کنم
یادم بندازید

M-Gheibi
یک شنبه 29 آذر 1383, 15:38 عصر
منم یک مقاله انگلیسی در این مورد دارم که خیلی کامله فقط باید جایی برای upload پیدا کنم
یادم بندازید
حجمش چقدر هست؟ اینجا نمیشه؟

بابک زواری
یک شنبه 29 آذر 1383, 16:22 عصر
فکر کنم زیاد باشه منم حجم مصرفیم داره تموم میشه

MM_Mofidi
سه شنبه 01 دی 1383, 14:10 عصر
با اجازه از دوستان
Sql Injection
http://www.nextgenss.com/papers/advanced_sql_injection.pdf
http://www.spidynamics.com/papers/SQLInjectionWhitePaper.pdf
http://www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf
http://www.oracle.com/technology/deploy/security/pdf/2003alert61.pdf
SQL Server 2000 Passwords
http://www.nextgenss.com/papers/cracking-sql-passwords.pdf

روانشناس
سه شنبه 01 دی 1383, 16:00 عصر
شما عزیزان همه استاد بنده هستید ولی اجازه بدید این چند خط رو هم من اضافه کنم.

1- در مورد اول که آقا بهروز فرمودن، در حقیقت تفاوت زمانی در استفاده از حلقه های While و For نیست. باید سعی کنید شرطها و دستورات داخل حلقه ها رو بهینه سازی کنید. به عنوان مثال همون کدی رو که آقا بهروز نوشتن بررسی کنید که چطور بهینه سازی شده. اجازه بدید این مطلب رو بصورت کلی بگم: هیچوقت در شروط حلقه ها از اشیا استفاده نکنید چونکه ارجاع به شی عمل زمانبریه. بازم به اون مثال آقا بهروز یه نگاهی بکنید.
2- در مورد SQL Injection بنده هم مطالب زیادی خوندم ولی خودم که تست کردم (با بانک اطلاعاتی Access 2003) این مورد به هیچوجه پیش نیومد. البته کار از محکم کاری عیب نمی کنه و بهتره یه برنامه نویس همیشه تمهیدات لازم رو بکار ببره. ضمن اینکه استفاده از Stored Procedure ها باعث بالا رفتن راندمان اجرای برنامه میشه.
3- نکته سوم یه نکته واضح و بدیهیه که متاسفانه در اکثر نرم افزارها فراموش میشه. نکته بسیار خوبی بود.
4- بنده کلا با این روش استفاده از توابع API در VB مخالفم. به نظر من بهتره از همون روش تعریف API ها استفاده کنیم و یا یه بار برای همیشه این تعاریف رو بنویسیم و هر دفعه اونو به پروژه اضافه کنیم. البته میشه این تعاریف رو بصورت فایلهای tlb هم در آورد. (اگه حالشو ندارید می تونید اسم فایلهای dll حاوی API ها رو با پسوند tlb سرچ کنید و بعد اونا رو دانلود کنید و در آخر هم که حالشو ببرید)

Hamedm
سه شنبه 01 دی 1383, 21:09 عصر
:thnx:

Behrouz_Rad
پنج شنبه 03 دی 1383, 07:20 صبح
سلام.

بنده کلا با این روش استفاده از توابع API در VB مخالفم. به نظر من بهتره از همون روش تعریف API ها استفاده کنیم و یا یه بار برای همیشه این تعاریف رو بنویسیم و هر دفعه اونو به پروژه اضافه کنیم.

مورد 4 جنبه پیشنهادی داشت.
صلاح کار عاقلان خود دانند.
:wise1: