PDA

View Full Version : مشکل در ذخیره عکس در sql با parameter



asman.abi
سه شنبه 05 خرداد 1394, 11:30 صبح
با سلام

در کد من که همه آشنا هستن یه مشکلی وجود داره که هنگامی که کد زیر را اجرا می کنم کار به درستی انجام میشه.

connection.com.CommandText = "insert into world(caption,form,topic,number,sal,mah,roz,sender ,picture) values('" + comboBox1.Text + "','" + comboBox2.Text + "','" + textBox1.Text + "','" + textBox2.Text + "','" + comboBox3.Text + "','" + comboBox4.Text + "','" + comboBox5.Text + "','" + textBox3.Text + "',@pict)";

connection.com.Parameters.AddWithValue("@pict", fd);
connection.com.ExecuteNonQuery();
در این جا متغیر fd یه متغیر از نوع باینری هست که اطلاعات عکس ما رو درونش داره و با دستور بالا وارد sql میشه.
ولی مشکل در ذخیره دوم است که با تغییر اطلاعات در همان پنجره در هنگام ذخیره اطلاعات با خطا مواجه می شم. مشکل از کجاست و چه جوری حل میشه. ممنون

خطا

131673

Davidd
سه شنبه 05 خرداد 1394, 11:45 صبح
سلام. شما در ذخیره دوم SqlCommand جدید نمیسازی و همون قبلی هست و چون قبلا یه پارامتر با نام @pict بهش اضافه کردی دوباره نمیشه یه پارامتر با همون نام اضافه کنی. یا SqlCommand در هر بار ذخیره دوباره new کن یا اینکه چک کن اگه پارامتر @pict وجود داره فقط بهش مقدار بده و add نکن.

asman.abi
چهارشنبه 06 خرداد 1394, 00:59 صبح
ممنون از پاسختون
من یکم کد رو باید توضیح بدم. connection یه کلاس هست که در اون متغییر com رو تعریف کردم
به این صورت
public static SqlCommand com=new SqlCommand();

پس در این کلاس وقتی من به صورت connection.com صدا می زنم خودش new می کنه. اگه نمی کنه بگید اصلاح کنم.
گفتم در پنجره ورود اطلاعات در مرتبه اول همه اطلاعات به درستی ذخیره می شه. ولی برای بار دوم که اطلاعات فرد دوم وارد میشه همون خطا رو میده. :اشتباه::ناراحت:

Davidd
چهارشنبه 06 خرداد 1394, 09:03 صبح
توضیح دادم که در بار دوم پارامتری که قبلا اضافه شده نمیشه دوباره اضافه کرد. از این کد استفاده کنید :
connection.com.CommandText = "insert into world(caption,form,topic,number,sal,mah,roz,sender ,picture) values('" + comboBox1.Text + "','" + comboBox2.Text + "','" + textBox1.Text + "','" + textBox2.Text + "','" + comboBox3.Text + "','" + comboBox4.Text + "','" + comboBox5.Text + "','" + textBox3.Text + "',@pict)";
onnection.com.Parameters.Clear();

connection.com.Parameters.AddWithValue("@pict", fd);

connection.com.ExecuteNonQuery();

asman.abi
چهارشنبه 06 خرداد 1394, 11:50 صبح
متشکر حله :لبخند::چشمک:

connection.com.Parameters.Clear();

Mahmoud.Afrad
چهارشنبه 06 خرداد 1394, 17:25 عصر
توصیه اکید میکنم همه اطلاعات رو با پارامتر ارسال کنید نه فقط عکس.

asman.abi
شنبه 09 خرداد 1394, 12:53 عصر
توصیه اکید میکنم همه اطلاعات رو با پارامتر ارسال کنید نه فقط عکس.

میشه دلیلتون رو بگید. :متفکر:

محمد آشتیانی
یک شنبه 10 خرداد 1394, 01:06 صبح
سلام
یک دلیلش جلوگیری از SQL Injection هست
خب این چه معنی میده؟ عرض می‌کنم.

شما این کوئری رو در نظر بگیرید (بدون استفاده از پارامتر)
"SELECT username FROM users WHERE userId =" + txtuid.Text

اگر شما مقدار تکست باکس txtuid رو مثلا 1 بدید ، طبیعتا در صورت موجود بودن نام کاربری شخصی که شناسه کاربریش 1 هست بعنوان نتیجه برگردونده میشه یعنی شکل کوئری می‌شود این:
SELECT username FROM users WHERE userId = 1

اما ، اگر یه بنده خدایی (بصورت دانسته) داخل txtuid این رو بنویسه:
0; Drop table users
چه اتفاقی میفته؟ شکل کوئری شما می‌شود این:
SELECT username FROM users WHERE userId = 0; Drop table users

نتیجه؟ جدول users شما به همین راحتی حذف می‌شود.
اما در صورتی که از پارامترها استفاده کنید این اتفاق نخواهد افتاد.

این یک مثال ساده بود ، حالا اون کوئری هر چیزی میتونه باشه ، فرض کنید همچین چیزی بجای اون کوئری DROP اجرا کنه
CREATE LOGIN [test] WITH PASSWORD=N'123', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
این که میدونید معنیش چیه؟ یک لاگین تر و تمیز در Sql Server می‌سازه و اون شخص مورد نظر می‌تونه به دیتابیس ها دسترسی پیدا کنه

به نظرتون این دلیل می‌تونه کافی باشه برای استفاده از پارامترها؟



موفق باشید.

ghasem110deh
یک شنبه 10 خرداد 1394, 01:17 صبح
نتیجه؟ جدول users شما به همین راحتی حذف می‌شود.
اما در صورتی که از پارامترها استفاده کنید این اتفاق نخواهد افتاد.


آقای آشتیانی اگه کاربر همون کد رو توی جعبه متن بنویسه (در صورت وجود پارامتر) چرا جدول حذف نمیشه ؟
منظورم اینه که چطور جلوگیری میکنه !؟
بخاطر اینه که متن مستقیم به کوئری اضافه نمیشه یا چی !؟

ممنون :)

asman.abi
یک شنبه 10 خرداد 1394, 01:22 صبح
ممنون از پاسخ
ولی از اون دلایل ضعیف بود. چرا؟ چون کاربر از جزییات پایگاه مطلع نیست که بخواد چنین کاری بکنه. دوما اگه با پارامتر هم انجام بشه نتیجه همونه:متعجب:

محمد آشتیانی
یک شنبه 10 خرداد 1394, 01:27 صبح
وقتی شما چیزی بعنوان پارامتر به کوئریتون ارسال می کنید ، از طرف SqlServer فقط به همین عنوان در نظر گرفته میشه و چیزی اجرا نمیشه (مثل اون کوئری که در پست قبل گفتم)
یعنی حتی اگر پارامتر شما از نوع رشته باشه و شما اون کوئری Drop رو بهش ارسال کنید ، SqlServer بهش به عنوان یک مقدار برای مقایسه نگاه میکنه

در واقع از نظر SqlServer با حالت بدون پارامتر کوئری شما این میشه
SELECT username FROM users WHERE userId = 0; Drop table users

اما با استفاده از پارامترها به این صورت خواهد بود
SELECT username FROM users WHERE userId = '0; Drop table users'
به اون کوتیشن ها در بخش WHERE دقت کنید

محمد آشتیانی
یک شنبه 10 خرداد 1394, 01:29 صبح
ممنون از پاسخ
ولی از اون دلایل ضعیف بود. چرا؟ چون کاربر از جزییات پایگاه مطلع نیست که بخواد چنین کاری بکنه. دوما اگه با پارامتر هم انجام بشه نتیجه همونه:متعجب:

دلیل ضعیفی بود؟ تصمیم با شماست دوست عزیزم.

پست اولم یک ویرایش داشت و یک مثال اضافه کردم و در پست دومم علت اینکه با پارامتر این اتفاق نمیفته رو شرح دادم.
ضمنا همیشه با کاربرها طرف نیستیم دوست گرامی ، عرض کردم برخی دانسته این کارها رو می کنند

asman.abi
یک شنبه 10 خرداد 1394, 02:16 صبح
من هر دو حالتی که شما گفتید رو آزمایش کردم. نتایج یکی بود.

در هر دو دستور (بدون پارامتر و با پارامتر) نتایج به صورت کتیشن وارد شدن و در مدخل خود قرار گرفتن و هیچ تغییری در پایگاه داده نشد. اگر به کد من در پست اول دقت کنید متوجه می شید که با کوتیشن تمام دستور وارد می شود.

محمد آشتیانی
یک شنبه 10 خرداد 1394, 02:28 صبح
ممنون الان مشخص شد.
ولی کسی به پایگاه دسترسی نداره و از فیلد های پایگاه مطلع نیست که چنین کاری کنه.
به فرض هم داشته باشه دیگه این کار لازم نیست از یه database managment استفاده میکنه و کارشو با اون انجام میده.

اون کوئری Dropیک مثال ساده بود فقط ، جای اون هر کوئری دیگری میتونه باشه

مثالی که برای ایجاد لاگین در SqlServer زدم کاملا نشون میده چقدر این مسئله اهمیت داره و این تنها یک نمونه بود برای روشن شدن داستان.
حالا فکر کنید این مسئله پیش و پا افتاده در صفحه لاگین یک سایت رعایت نشده باشه
یا در یک برنامه کلاینت سروری

می‌بینید که به سادگی با ساختن یک لاگین روی SqlServer میشه از هر سیستمی به Database Engine وصل شد و هر کاری انجام داد.

دیدتون رو از برنامه های تک کاربره که دیتابیس روی همون سیستم هست فراتر ببرید


موفق باشید.

ali_72
یک شنبه 10 خرداد 1394, 07:00 صبح
asman.abi (http://barnamenevis.org/member.php?285323-asman-abi) عزیز سعی کن به entity سوئیچ کنی
کدنویسی آسان و سریع تر میشه

ebrahim.rayatparvar
یک شنبه 10 خرداد 1394, 11:14 صبح
سلام بر مهندسین عزیز.
من داشتم مطالبی رو که مهندس آشتیانی عزیز نوشتن رو نگاه میکردم و سوالات دوستان که ظاهرا هنوز برای بعضی ها گنگ بود چزا با پارامتر استفاده کرد بهتره که باید حرف مهندس رو اینجا تاکید کنم به دیلیل SQL Injection که برای جلوگیری بیشتر از این نوع ورود بهتره باز هم پارامتر و هم Strod Precudre استفاده کنید این راه کار برای بیشتر کسایی که توی دنیای نفوذ هستن البته نه همه و لی بیشتر تازه کارا که خیلی زیاد هستن خیلی خوبه چون زمانی که شما میگید پارامتر حالا هر چیزی بزنید ولی اون مقدار به عنوان یک پارامتر فلان فیلد میرود و اگه بدون پارامتر بزنید میشه مثال ساده ای که مهندس زدن ولی از اون بدتر اینه که با تزریق کد sql با select و union به راحتی میشه نام دیتابیس، جدول ها ، مقدار جدول های و خیلی کار های دیگه کرد که این امر از نظر امنیتی یک فاجعه حساب میشه. شما در مورد سایت ها و sql injection تحقیق کنید هنوز هنوزه خیلی سایت ها دارند با sql inject میشن حتی تو کشور عزیزمون ایران که البته خدار رو شکر باید گفت طبق چیزایی که من دیدم خیلی کمتر از کشور های دیگه هست. اما اگه به این نوع پارامتر هنوز نمیدونید با یه مثال ساده با عکس میشه نشون داد وقتی SQL injection بشه چه مشکلی پیش میاد اگه مهندس آشتیانی اجازه بدن.

asman.abi
یک شنبه 10 خرداد 1394, 23:39 عصر
ولی من تست کردم نتایج چرا یکی بود؟
واقعا چرا؟
من هم با پارامتر زدم هم بدون پارامتر با همون دستوراتی که آقای آشتیانی زد. ولی نتایج یکی بود.

شما امتحان کنید. ببینید همینه !


مشکل آقای آشتیانی اینه که اصلا به کد توجه نکرده و پست زده.

اگه من این طور شما نوشته کد زده بودم درست ولی من اصلا این گونه کد نمی زنم. مشکل شما در کد نویسی هست نه parameter

asman.abi
سه شنبه 12 خرداد 1394, 15:29 عصر
پس هیچ فرقی نداره.
امتحان کردن دیدن فرقی نداره.:تشویق:

Mahmoud.Afrad
سه شنبه 12 خرداد 1394, 19:36 عصر
ولی من تست کردم نتایج چرا یکی بود؟
واقعا چرا؟
من هم با پارامتر زدم هم بدون پارامتر با همون دستوراتی که آقای آشتیانی زد. ولی نتایج یکی بود.

شما امتحان کنید. ببینید همینه !


مشکل آقای آشتیانی اینه که اصلا به کد توجه نکرده و پست زده.

اگه من این طور شما نوشته کد زده بودم درست ولی من اصلا این گونه کد نمی زنم. مشکل شما در کد نویسی هست نه parameter
یک عکس یا کد بزار ببینیم چجوری تست کردی.


برای مثال به صورت زیر عمل کن نتیجه رو بگو. البته اول از دیتابیس یک بکاپ بگیر
کوئری بدون پارامتر چیزی شبیه کد زیر

cmd.CommandText = "SELECT * FROM tbl01 where id=" + textBox1.Text;

از کدهای دیگه صرف نظر کردم.
حالا برنامه رو اجرا کن و در تکست باکس متن زیر رو کپی کن و دکمه رو بزن

0;EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";EXEC sp_MSForEachTable "DELETE FROM ?";

حالا اگر جداول رو ببینی میبینی همه اطلاعات پاک شدن.
حالا اگر کوئری رو با پارامتر مقدار بدی حتی اگر در تکست باکس همون متن رو کپی کنی اطلاعات جداول پاک نخواهد شد.

asman.abi
چهارشنبه 13 خرداد 1394, 23:22 عصر
آفرین واقعا شما نگاه به کد نکردید در پست اول من

یه نگاه بندازید بد نیستا!

شما رو کد من توضیح بده. من امتحان کردم و فرقی نداشته در کد من، نه کد شما! (دقت کنید) چقدر بگم.

asman.abi
چهارشنبه 13 خرداد 1394, 23:23 عصر
اضلا باید این جوری کد رو زد. نه روش غلط شما

محمد آشتیانی
پنج شنبه 14 خرداد 1394, 11:03 صبح
سلام
روش صحیح گفته شد ، شما هم میتونی به کارت با روش خودت ادامه بدی و از مزایاش بهره مند بشی.
بحث با کسی که تفکرات اینچنینی داره بی فایدست.


موفق باشید.

Mahmoud.Afrad
پنج شنبه 14 خرداد 1394, 11:54 صبح
آفرین واقعا شما نگاه به کد نکردید در پست اول من

یه نگاه بندازید بد نیستا!

شما رو کد من توضیح بده. من امتحان کردم و فرقی نداشته در کد من، نه کد شما! (دقت کنید) چقدر بگم.
فقط برای اینکه ثابت بشه کدت آسیب پذیره این پست رو میزنم.
برنامه خودت رو اجرا کن و در تکست باکس1 متن زیر رو کپی کن و دکمه ثبت رو بزن
',null,null,null,null,null,null); EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";EXEC sp_MSForEachTable "DELETE FROM ?";--