Makale Özeti

Birçok uygulamada kullanabileceğiniz güvenlik resimlerinin oluşturulmasını anlatan faydalı bir döküman.

Makale

Merhabalar. Bu yazımda, çoğumuzun web projelerinde ihtiyaç duyabileceği, önemli bir güvenlik ayrıntısını irdeliyeceğiz. Bir çok üyelik gerektiren websitelerinde gördüğümüz, güvenlik resimlerinin nasil oluşturulacağını inceleyeceğiz.

Öncelikle dikkat etmemiz gereken noktalara bakalim. Amacımız herhangi bir program tarafindan okunamayacak, image processing ya da benzeri algoritmalarla yorumlanamayacak fakat buna karşılık, gerçek bir kullanıcı, bir insan tarafindan çok kolay anlaşılabilecek resimler oluşturmak. Bunun için yapabileceklerimiz:

· Yeterli derecede background ve text kirliliği, dağınıklığı sağlamak

· Mümkün olduğunca birbirinden farklı, birbirine benzemeyen resimler kullanmak

· Olabildiğince çok resim kullanmak

· Resimlerin dosya büyüklüklerini (file size) mümkün olduğunca birbirine yakın hatta aynı boyutta tutmak.

Son iki madde, gerçekten çok dikkat edilmesi gereken bir özellik. Bir çok sitede,bu tarz resimler 20-30 adetle sınırlandırılmış ve de hepsinin dosya boyutları faklı olan resimler kullanılmakta. Bunların çoğunluğu image processing gibi işlemlere okunması zor olan resimler olsa da, designerlarin gözden kacırdıkları, cok daha büyük bir güvenlik açığı yaratmakta. Dosyaların büyüklükleri ve içerisindeki yazılar bir kez tespit edildikten sonra, bir program aracılığı ile flood işlemleri rahatlıkla gerçekleştirilebilir.

Peki, yapabileceğimiz ne var? Bu konuda en iyi çözüm; resmi run-time da random olarak oluşturmak ve bu şekilde içeriğindeki yazıyı kontrol etmek. Yani, örneğin, sayfa her refresh olduğunda, yeni bir kod, bu kodun resimsel, kirletilmiş, anlaşılması güçleştirilmiş hali ve de her seferinde aynı dosya adında, yaklaşık olarak aynı dosya boyutunda yeni bir resim üretmek.

Aşağıda kodunu gördüğümüz Img classı textten image oluşturmak için bütün işlemleri gerçekleştirmekte.

public class Img

{

#region properties

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; }

}

private string text;

private int width;

private int height;

private string familyName;

private Bitmap image;

#endregion

private Random random = new Random();

//uretilen kodu, yukseklik ve de genisligi kullanarak yeni bir image uretelim

public Img(string s, int width, int height)

{

text = s;

this.width = width;

this.height = height;

ImageYarat();

}

//Urettigimiz kodumuzu stringten image ceviriyoruz.

private void ImageYarat()

{

this.familyName = System.Drawing.FontFamily.GenericSerif.Name;

// 32bit bmp yaratalim

Bitmap bitmap = new Bitmap(this.width, this.height, PixelFormat.Format32bppArgb);

// cizim icin bir graphics nesnesi yaratalim.

Graphics g = Graphics.FromImage(bitmap);

g.SmoothingMode = SmoothingMode.AntiAlias;

Rectangle rec = new Rectangle(0, 0, this.width, this.height);

// Resimde arka alani dolduralim

HatchBrush hb = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White);

g.FillRectangle (hb, rec);

Font font = new Font(this.familyName, 44, FontStyle.Bold);

// textin formatini belirleyelim

StringFormat format = new StringFormat();

format.Alignment = StringAlignment.Center;

format.LineAlignment = StringAlignment.Center;

// bir path belirleyip, texte random olarak aci verelim

GraphicsPath path = new GraphicsPath();

path.AddString(this.text, font.FontFamily, (int) font.Style, font.Size, rec, format);

float v = 4;

PointF[] p =

{

new PointF(this.random.Next(rec.Width) / v, this.random.Next(rec.Height) / v),

new PointF(rec.Width - this.random.Next(rec.Width) / v, this.random.Next(rec.Height) / v),

new PointF(this.random.Next(rec.Width) / v, rec.Height - this.random.Next(rec.Height) / v),

new PointF(rec.Width - this.random.Next(rec.Width) / v, rec.Height - this.random.Next(rec.Height) / v)

};

Matrix matrix = new Matrix();

matrix.Translate(0F, 0F);

path.Warp(p, rec, matrix, WarpMode.Perspective, 0);

// texti cizelim

hb = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray);

g.FillPath(hb, path);

// biraz da gurultu/kirlilik ekleyelim

for (int i = 0; i < (int) (rec.Width * rec.Height / 30); i++)

{

int x = this.random.Next(rec.Width);

int y = this.random.Next(rec.Height);

int w = this.random.Next(rec.Width / 50);

int h = this.random.Next(rec.Width / 40);

g.FillEllipse(hb, x, y, w, h);

}

//image hazir...

this.image = bitmap;

}

}

Kodda da gördüğümüz gibi öncelikle graphics object kullanarak bir resim oluşturduk, arka alanını doldurduk, textin fontunu, formatini belirledik, texte bir path belirleyip bir perspektif ve açı kazandırdık ve son olarak, resmimize gürültü ekledik. ıstenirse, bu class çok daha geliştirilebilinir. Mesela : textin, back groundun ya da gürültünün rengi random olarak değiştirilebilinir, font-family random atanabilir....

İşte bu kadar, geriye kalan iş; bu classı çağıracak uygun web formları oluşturmak. Bunun için de iki ayrı web forma ihtiyacımız var. Bir tanesi resimi yaratacak olan img clasını çağıracak ve bir image gibi davranacak olan web form, diğeri de default.aspx olan, kodu random olarak üreten, girilen kod ile doğruluğunu test eden ve de içerisine image web formunu <img> tagı ile çağıran formumuz.

JpegImage.aspx.cs

private void Page_Load(object sender, System.EventArgs e)

{

// bitmap imagei session degerini kullanarak uret.

Img ci = new Img(this.Session["ImageKod"].ToString(), 200, 50);

//Response Headerini Jpeg imageye cevir

this.Response.Clear();

this.Response.ContentType = "image/jpeg";

//resmi, response streame jpeg formatinda yazalim

ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg);

//ci.Dispose();

}

Gördüğümüz gibi, JpegImage.aspx.cs img classını çağırarak 200*50 bir resim oluşturmakta.

JpegImage.aspx

Default.aspx.cs

private Random random = new Random();

private void Page_Load(object sender, System.EventArgs e)

{

if (!this.IsPostBack)

// Random bir kod uretip o kodu sessionda tutalim.

this.Session["ImageKod"] = RandomKodUret();

else // postback olduysa kod kontrolu

{

if (this.txtKod.Text == this.Session["ImageKod"].ToString())

{

//dogru

Session.Add("Guvenlik",true);

this.lblMessage.Text = "Dogru..!";

}

else

{

// yanlis

this.lblMessage.Text = "Hata..!";

// kodu degistir

this.txtKod.Text = "";

this.Session["ImageKod"] = RandomKodUret ();

}

}

}

// 6 rakamli random bir sayi uretir

private string RandomKodUret()

{

string s = "";

for (int i = 0; i < 6; i++)

s = String.Concat(s, this.random.Next(10).ToString());

return s;

}

Default.aspx.cs’de gördüğümüz gibi, page refresh olduğunda random bir sayı üretir. Ben bu sayının 6 rakam olmasını uygun görüyorum. 000000’dan 999999’a kadar 1milyon farklı resim elde edebiliriz, bu da fazlasıyla memnuniyet verici bir sayı. Session objesine attığımız textimizi, postback sırasında kontrol ederek, girilen değerle doğruluğunu karşılaştırıyoruz.

Son olarak, default.aspx’e de bakalim.

Default.aspx
<form id="Default" method="post" runat="server">
<img src="JpegImage.aspx">
<strong>Şifreniz :</strong>
<asp:TextBox id="txtKod" runat="server" Width="136px"></asp:TextBox>
<asp:Button id="btnSubmit" runat="server" Text="Gonder"></asp:Button>
<em class="notice">Not: Eger sifrenizi okuyamiyorsaniz,<br>sayfayi
yenileyiniz.</em> <br> <p><asp:Label id="lblMessage" runat="server"></asp:Label></p>
</form>

JpegImage.aspx’i <img> tag i ile cagirarak, projemizi tamamliyoruz.

Kodu indir

Hepimize iyi calismalar.

Kıvanç ÖZÜÖLMEZ