تقنيات مبرمجى ASP.NETيناقش هذا المنتدى برمجة صفحات ويب لتعمل من جهة السيرفر باستخدام منصة الدوت نت باحدى لغاتها المختلفة VB.NET C# J# C++/CLI Delphi .NET
ويناقش القسم أيضا كل مايتعلق ببرمجة ال XML Web Services وطرق تصميمها
كيف تحمي نماذجك من أن تعبئ بشكل آلي ؟
كثيراً ما نجد مواقع إنترنت تطلب منا كتابة كلمة موجودة في صورة مثل هذه:
هل فكرت في يوم عن وظيفة هذه الصورة المشوهة؟
عندما يوجد نموذج Form في احدى صفحات الإنترنت، يستطيع مبرمج ما كتابة كود بسيط يقوم بتعبئة النموذج بشكل آلي، و ببيانات عشوائية، و هذا من شأنه ملئ موقعك ببيانات وهمية بالإضافة إلى إشغال موقعك و جلعله يعمل بشكل أبطأ.
لذلك كان لابد من وجود طريقة للتفريق بين أن من يقوم بتعبئة النموذج هو إنسان أو آله (حاسب آلي)!! و لهذا ظهر مصطلح CAPTCHA .
CAPTCHA يهدف في أن توضع صورة مشوهة مثل التي في الأعلى بحيث لن يستطيع التعرف على هذه الصورة و قراءة محتواها إلى إنسان، و لكن ما هو الهدف من جعلها مشوهة؟
الصورة تكون مشوهة لأن بعض البرامج تكون ذكية جداً، فبإمكانها التعرف على ما بداخل الصورة عن طريق التعرف الضوئي على الكتابة العربية أو ما يعرف OCR و لذلك يكون محتوى الصورة مشوه لكي لا يستطيع البرنامج قرائتها (و حتى كتابة هذه السطور الحاسب الآلي غير قادر على مجارات عقل الإنسان في التعرف على الصور و الإنماط).
الآن من المفترض أن نكون قد عرفنا السبب في وجود هذه الصور المشوهة المحتوى.
في البداية أنشئ صفحة و لنسميها Default.aspx و لنضع فيها:
Image اسمها Image1
TextBox اسمها TextBox1
Label اسمه Label1
Button اسمه Button1
و لنضع هذا الكود بداخل ملف Default.aspx.cs:
كود PHP:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
// For generating random numbers.
private Random random = new Random();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Create a random code and store it in the Session object.
Session["CaptchaImageText"] = GenerateRandomCode();
}
else
{
// On a postback, check the user input.
if (TextBox1.Text == Session["CaptchaImageText"].ToString())
{
// Display an informational message.
Label1.CssClass = "info";
Label1.Text = "Correct!";
}
else
{
// Display an error message.
Label1.CssClass = "error";
Label1.Text = "ERROR: Incorrect, try again.";
// Clear the input and create a new random code.
TextBox1.Text = "";
Session["CaptchaImageText"] = GenerateRandomCode();
}
}
}
//
// Returns a string of six random digits.
//
private string GenerateRandomCode()
{
string s = "";
for (int i = 0; i < 6; i++)
s = String.Concat(s, this.random.Next(10).ToString());
return s;
}
}
في هذا الكود قمنا بانشاء رقم عشوائي و حفظة في Session اسمها CaptchImageText و تتغير كلما عملنا PageRefrsh
الآن للنشئ صفحة اسمها JpegImage.aspx و نضع الكود التالي في الملف JpegImage.aspx.cs
كود PHP:
protected void Page_Load(object sender, EventArgs e)
{
// Create a CAPTCHA image using the text stored in the Session object.
CaptchaImage ci = new CaptchaImage(this.Session["CaptchaImageText"].ToString(), 200, 50, "Century Schoolbook");
// Change the response headers to output a JPEG image.
this.Response.Clear();
this.Response.ContentType = "image/jpeg";
// Write the image to the response stream in JPEG format.
ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg);
// Dispose of the CAPTCHA image object.
ci.Dispose();
}
هنا سوف نقوم بأنشاء الصورة و سيكون محتواها هو ما هو موجود في الـ Session التي أنشأناها في الصفحة Default.aspx ثم سوف نجعل هذه الصفحة تنتج ملف Jpeg بدلاً من HTML.
الآن في الصفحة Default.aspx نختار Image1 و نذهب للخصائص Properties و نضع القيمة ImageUrl تساوي الصفحة التي قمنا بإنشائها JpegImage.aspx.
الآن و المرحلة الأخيره هي انشاء كلاس Class اسمه CaptchaImage.cs ( و هي المسؤولة عن انشاء الصورة و تشويهها عمل Noise للخلفيه) و نضع فيه الكود التالي:
كود PHP:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
/// <summary>
/// Summary description for CaptchaImage
/// </summary>
public class CaptchaImage
{
// Public properties (all read-only).
public string Text
{
get { return this.text; }
}
public Bitmap Image
{
get { return this.image; }
}
public int Width
{
get { return this.width; }
}
public int Height
{
get { return this.height; }
}
// Internal properties.
private string text;
private int width;
private int height;
private string familyName;
private Bitmap image;
// For generating random numbers.
private Random random = new Random();
// ====================================================================
// Initializes a new instance of the CaptchaImage class using the
// specified text, width and height.
// ====================================================================
public CaptchaImage(string s, int width, int height)
{
this.text = s;
this.SetDimensions(width, height);
this.GenerateImage();
}
// ====================================================================
// Initializes a new instance of the CaptchaImage class using the
// specified text, width, height and font family.
// ====================================================================
public CaptchaImage(string s, int width, int height, string familyName)
{
this.text = s;
this.SetDimensions(width, height);
this.SetFamilyName(familyName);
this.GenerateImage();
}
// ====================================================================
// This member overrides Object.Finalize.
// ====================================================================
~CaptchaImage()
{
Dispose(false);
}
// ====================================================================
// Releases all resources used by this object.
// ====================================================================
public void Dispose()
{
GC.SuppressFinalize(this);
this.Dispose(true);
}
// ====================================================================
// Custom Dispose method to clean up unmanaged resources.
// ====================================================================
protected virtual void Dispose(bool disposing)
{
if (disposing)
// Dispose of the bitmap.
this.image.Dispose();
}
// ====================================================================
// Sets the image width and height.
// ====================================================================
private void SetDimensions(int width, int height)
{
// Check the width and height.
if (width <= 0)
throw new ArgumentOutOfRangeException("width", width, "Argument out of range, must be greater than zero.");
if (height <= 0)
throw new ArgumentOutOfRangeException("height", height, "Argument out of range, must be greater than zero.");
this.width = width;
this.height = height;
}
// ====================================================================
// Sets the font used for the image text.
// ====================================================================
private void SetFamilyName(string familyName)
{
// If the named font is not installed, default to a system font.
try
{
Font font = new Font(this.familyName, 12F);
this.familyName = familyName;
font.Dispose();
}
catch (Exception ex)
{
this.familyName = System.Drawing.FontFamily.GenericSerif.Name;
}
}
// ====================================================================
// Creates the bitmap image.
// ====================================================================
private void GenerateImage()
{
// Create a new 32-bit bitmap image.
Bitmap bitmap = new Bitmap(this.width, this.height, PixelFormat.Format32bppArgb);
// Create a graphics object for drawing.
Graphics g = Graphics.FromImage(bitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(0, 0, this.width, this.height);
// Fill in the background.
HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White);
g.FillRectangle(hatchBrush, rect);
// Set up the text font.
SizeF size;
float fontSize = rect.Height + 1;
Font font;
// Adjust the font size until the text fits within the image.
do
{
fontSize--;
font = new Font(this.familyName, fontSize, FontStyle.Bold);
size = g.MeasureString(this.text, font);
} while (size.Width > rect.Width);
// Set up the text format.
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
// Create a path using the text and warp it randomly.
GraphicsPath path = new GraphicsPath();
path.AddString(this.text, font.FontFamily, (int)font.Style, font.Size, rect, format);
float v = 4F;
PointF[] points =
{
new PointF(this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),
new PointF(rect.Width - this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),
new PointF(this.random.Next(rect.Width) / v, rect.Height - this.random.Next(rect.Height) / v),
new PointF(rect.Width - this.random.Next(rect.Width) / v, rect.Height - this.random.Next(rect.Height) / v)
};
Matrix matrix = new Matrix();
matrix.Translate(0F, 0F);
path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);
// Draw the text.
hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray);
g.FillPath(hatchBrush, path);
// Add some random noise.
int m = Math.Max(rect.Width, rect.Height);
for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++)
{
int x = this.random.Next(rect.Width);
int y = this.random.Next(rect.Height);
int w = this.random.Next(m / 50);
int h = this.random.Next(m / 50);
g.FillEllipse(hatchBrush, x, y, w, h);
}
الآن نفذ البرنامج و كل شيئ من المفترض أن يعمل بشكل جيد كما في الشكل الموجود في أعلى الموضوع.
أحب أن انوه أن هذا المثال ينتج CAPTCHA بسيطة جداً تتكون من أرقام فقط، و الكود لإنتاج الأرقام موجود و من الممكن أن تغير فيها لكي ينتج ارقام و حروف أو حتى كلمات.