ウェブサイトでよく使用されるCAPTCHA画像の生成方法について解説します。主な実装手順は以下の通りです:
- HttpHandlerを使用してランダムなCAPTCHA画像を生成
- JavaScriptで非同期に画像を更新
実装例
以下のコードはASP.NETでCAPTCHA画像を生成するHttpHandlerの実装例です:
public class CaptchaGenerator : IHttpHandler
{
private static readonly Random random = new Random();
private static readonly Brush[] availableBrushes = GetAvailableBrushes();
private static readonly Pen[] availablePens = GetAvailablePens();
private const int CharWidth = 45;
private const int ImageHeight = 60;
public void ProcessRequest(HttpContext context)
{
int charCount = 6;
if (!string.IsNullOrEmpty(context.Request.QueryString["count"]))
{
int.TryParse(context.Request.QueryString["count"], out charCount);
}
using (Bitmap image = new Bitmap(CharWidth * charCount, ImageHeight))
using (Graphics graphics = Graphics.FromImage(image))
{
graphics.Clear(Color.White);
string captchaText = GenerateRandomText(charCount);
DrawText(graphics, captchaText);
DrawNoise(graphics, image.Width, image.Height);
context.Response.ContentType = "image/jpeg";
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
private string GenerateRandomText(int length)
{
const string chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
private void DrawText(Graphics graphics, string text)
{
for (int i = 0; i < text.Length; i++)
{
Brush brush = availableBrushes[random.Next(availableBrushes.Length)];
graphics.DrawString(
text[i].ToString(),
new Font("Arial", CharWidth - 10, FontStyle.Bold),
brush,
new PointF(i * CharWidth + 5, 5));
}
}
private void DrawNoise(Graphics graphics, int width, int height)
{
int noiseCount = random.Next(15, 25);
for (int i = 0; i < noiseCount; i++)
{
Pen pen = availablePens[random.Next(availablePens.Length)];
PointF start = new PointF(random.Next(width), random.Next(height));
PointF end = new PointF(random.Next(width), random.Next(height));
graphics.DrawLine(pen, start, end);
}
}
private static Brush[] GetAvailableBrushes()
{
return typeof(Brushes).GetProperties(BindingFlags.Public | BindingFlags.Static)
.Where(p => p.PropertyType == typeof(Brush) && p.Name != "White")
.Select(p => (Brush)p.GetValue(null))
.ToArray();
}
private static Pen[] GetAvailablePens()
{
return typeof(Pens).GetProperties(BindingFlags.Public | BindingFlags.Static)
.Where(p => p.PropertyType == typeof(Pen))
.Select(p => (Pen)p.GetValue(null))
.ToArray();
}
public bool IsReusable => false;
}
HTMLでの使用方法
生成したCAPTCHAをページに表示する方法:
<div id="captcha-container">
<img id="captcha-image" src="/CaptchaGenerator.ashx?count=6" alt="CAPTCHA" />
<button onclick="refreshCaptcha()">画像を更新</button>
</div>
<script>
function refreshCaptcha() {
var img = document.getElementById('captcha-image');
img.src = '/CaptchaGenerator.ashx?count=6&t=' + new Date().getTime();
}
</script>
この実装では、以下の点に注意してください:
- セキュリティ向上のため、単純な数字ではなく英数字混合を使用
- 画像更新時にキャッシュを回避するため、タイムスタンプパラメータを追加
- 視認性を考慮し、背景色を白に設定