PDA

View Full Version : آموزش: چگونه از کپچایی که نوشتم استفاده کنم؟



MasoudAdmin
سه شنبه 27 تیر 1402, 23:13 عصر
با سلام
در صفحه لاگین وبم کپچا استفاده کردم منتهی تابع کپچا رو در Page_Load هم گذاشتم که وقتی صفحه بار اول لود میشه کپچا هم اجرا بشه. الان مشکلی که دارم وقتی کلید ورود رو می زنم کپچا هم تغییر میکنه و با این مسئله همیشه پیغام میده که کلمه امنیتی صحیح نیست.
این کد ساخت کپچا هست:

private void CreateCaptha()
{
string Captcha = "QWERTYUIOPASDFGHJKLZXCVBNM0123456789";
Random Rand = new Random();
Object Captcha1 = Rand.Next(1, 36);
Object Captcha2 = Rand.Next(1, 36);
Object Captcha3 = Rand.Next(1, 36);
Object Captcha4 = Rand.Next(1, 36);
Object Captcha5 = Rand.Next(1, 36);
Object Captcha6 = Rand.Next(1, 36);
string StrCapcha1 = Captcha.Substring(Convert.ToInt32(Captcha1), 1);
string StrCapcha2 = Captcha.Substring(Convert.ToInt32(Captcha2), 1);
string StrCapcha3 = Captcha.Substring(Convert.ToInt32(Captcha3), 1);
string StrCapcha4 = Captcha.Substring(Convert.ToInt32(Captcha4), 1);
string StrCapcha5 = Captcha.Substring(Convert.ToInt32(Captcha5), 1);
string StrCapcha6 = Captcha.Substring(Convert.ToInt32(Captcha6), 1);
string ResultCaptcha = StrCapcha1 + StrCapcha2 + StrCapcha3 + StrCapcha4 + StrCapcha5 + StrCapcha6;
CaptchaText = ResultCaptcha;
Bitmap SecImage = new Bitmap(Server.MapPath("~/LayoutImage/BackGroundCaptcha.jpg"));
Graphics GrapgImage = Graphics.FromImage(SecImage);
GrapgImage.DrawString(ResultCaptcha.ToString(), new Font("Arial", 20, FontStyle.Strikeout), SystemBrushes.WindowText, new PointF());
SecImage.Save(Server.MapPath("~/LayoutImage/SecurityImage.jpg"));
this.CapchaImage.ImageUrl = "~/LayoutImage/SecurityImage.jpg";
}



protected void Page_Load(object sender, EventArgs e)
{
this.CreateCaptha();
}


اینم تگ کلید ورود:


<asp:Button ID="btnCMELogin" runat="server" Text="ورود" class="btn btn-outline-light btn-lg px-5" type="button" name="btnLogin" OnClick="btnCMELogin_Click"/>


اینم کد کلید ورود:

if(this.txtCapcha.Text.Trim()!=CaptchaText)
{
this.lbMessage.Text = "مقدار ورودی امنیتی اشتباه می باشد";
}



الان چجوری می تونم این مشکل رو رفع کنم؟ به صورتیکه وقتی کلید ورود رو می زنم کپچا مقدارش تغییر نکنه و اگر واقعا اشتباه وارد کرد مقدار جدید بگیره؟

ممنون میشم راهنمایی کنید.

mazoolagh
چهارشنبه 28 تیر 1402, 10:03 صبح
سلام و روز خوش
معمولا هر کدی که در page_load میاد باید تو یک بلوک if ispostback باشه!

MasoudAdmin
چهارشنبه 28 تیر 1402, 23:44 عصر
سلام. ممنون از پاسخ ولی با این مورد هم حل نشد.:ناراحت::افسرده:

MasoudAdmin
یک شنبه 01 مرداد 1402, 20:51 عصر
سلام دوستان. کسی پیشنهاد یا راه حلی واسه این مورد بنده نداره؟:متفکر:

mazoolagh
دوشنبه 02 مرداد 1402, 14:22 عصر
شما در همون page_load وضعیت کپچا رو هم باید در session تست کنین که مقدار داره یا نه؟
و این که اگه مقدار داره درسته یا نه؟

اینجوری میتونین حالت های مختلف رو از هم تشخیص بدین.

MasoudAdmin
دوشنبه 02 مرداد 1402, 21:39 عصر
با سلام. ممنون با توجه به اینکه واسه کپچا من یک تابع ساختم و اون تابع رو در page_load فراخوانی کردم میشه راهنمایی بفرمایید چجوری session رو تست کنم؟
گفتم چون دارم تازه کار می کنم اگر ممکن هست با توجه به کدهایی که گذاشتم ممنون میشم کدم رو اصلاح کنید یا نمونه کد بگذارید تا متوجه بشم.
بازم ممنون.
154825

mazoolagh
سه شنبه 03 مرداد 1402, 16:06 عصر
سلام دوباره
یک روش کار اینجوری هست که:

1- اول یک روتین مینویسیم که تصویر کپچا رو بسازه - فرضا اسمش GetCaptchaImage باشه.
البته روشی که شما استفاده کردین اشکال داره که باید درست بشه و بعدا توضیح میدم اشکالش و روش درست کردنش رو.
این روتین 2 جا استفاده میشه. یکبار در در page load (البته اگر ispostback نباشه) ، جای دیگه در button click برای رفرش کردن کپچا هست (که شما در فرم تون نذاشتین و باید اضافه کنین)

در همین روتین هست که متن و تصویر کپچا توسط روتین Createcaptcha ساخته و متن کپچا به session اضافه میشه:
void CreateCaptcha()
{
...
...
string CaptchaString= your code to create random string;
session.add( "CaptchaString" , CaptchaString );
...
...
}


2- در page load اینجوری مینویسیم:
{
if (!ispostback) { GetCaptchaImage(); }
}

3- در login click اینجوری مینویسیم:
if (session["CaptchaString"] != null)
{
if ( CaptchaText.text.trim().equals(session["CaptchaString"]) )
{
if ( Authenticated(UserName.text, Password.text) )
{ response.redirect("your defaultpage.aspx"); }
else { FailureText.text= "Invalid UserName or Password"; }
}
else
{ FailureText.text= "Invalid Captcha"; }
}
که تابع authenticated برای بررسی درست بودن username/password هست:
bool Authenticated(string Username, string Password)
{
return ( your code to verify username/password);
}

و FailureText اسم Labelی هست که در فرم لاگین اضافه کردیم و کاربردش هم مشخصه.

mazoolagh
سه شنبه 03 مرداد 1402, 16:56 عصر
همینجور که گفتم هم کد CreateCaptcha شما و هم روش گرفتن تصویر برای کنترل asp:image اشکال داره.

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

دویم این که برای ابجکتهایی مثل bitmap و graphics حتما باید از using استفاده کنین تا dispose بشن و گرنه با هر بار اجرا حافظه جدید اشغال میکنن و به مرور سایت میخوابه.

شما 2 راه دارین:
1- به همین روش ادامه بدین ولی به ازای هر کاربر (در واقع session) یک تصویر با اسم یکتا بسازین.
البته درست هست و کار میکنه، ولی باید حواستون باشه که پس از نمایش پاکش کنین وگرنه اون فولدر بتدیج بزرگ و پر میشه از فایل های بی مصرف،
و این که واقعا نیازی به این کار نیست.

2- تصویر رو بجای ذخیره روی دیسک به صورت یک استریم دربیارین.
برای این کار یک پیج جدا میسازیم (مثلا CaptchaImage.aspx) و content اون رو به image تغییر میدیم.
بعد کافی هست این پیج رو به عنوان imageurl کنترل asp:image معرفی کنیم.

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

protected void Page_Load(object sender, EventArgs e)
{
Response.ContentType = "image/jpeg";
CreateCaptcha();
}


void CreateCaptcha()
{
int i;
StringBuilder chars_sb = new StringBuilder();
for (i = (int)'0'; i <= (int)'9'; i++)
chars_sb.Append((char)i);
for (i = (int)'A'; i <= (int)'Z'; i++)
chars_sb.Append((char)i);
for (i = (int)'a'; i <= (int)'z'; i++)
chars_sb.Append((char)i);
string Chars = chars_sb.ToString();
// Chars : '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm nopqrstuvwxyz'


Random Rnd = new Random();
StringBuilder sb = new StringBuilder();
for (i = 1; i <= 6; i++)
sb.Append(Chars[Rnd.Next(Chars.Length)]);
string CaptchaString = sb.ToString();
Session.Add("CaptchaString", CaptchaString);
using (Bitmap SecImage = new Bitmap(Server.MapPath("~/LayoutImage/BackGroundCaptcha.jpg")))
{
using (Graphics g = Graphics.FromImage(SecImage))
{
g.DrawString(CaptchaString, new Font("Courier New", 20, FontStyle.Strikeout), Brushes.Yellow, new Point(0, 0));
SecImage.Save(Response.OutputStream, ImageFormat.Jpeg);
}
}
}

هر بار که این پیج رفرش بشه یک کپچا جدید میسازه:
154826

mazoolagh
سه شنبه 03 مرداد 1402, 17:13 عصر
حالا روتین GetCaptchaImage رو در فرم لاگین تکمیل میکنیم:
void GetCaptchaImage()
{
CaptchaImage.ImageUrl = "CaptchaImage.aspx";
}

همین!

MasoudAdmin
سه شنبه 03 مرداد 1402, 20:39 عصر
سلام. سپاس فراوان از زاهنمایی شما.