Поиск на сайте
Главная Журнал Форум Wiki DRKB Страны мира

Серверный контрол КАПЧА для ASP.NET

Сейчас уже каждый знает, что такое спам. На сегодняшний день существует два основных метода борьбы с автоматической рассылкой нежелательной информации: Байесовская фильтрация (POPFile) и запрос в виде искажённой картинки, требующий ответа пользователя. Конечно, оба этих подхода имеют свои плюсы и минусы. Здесь мы обсудим второй способ: проверки, что входящие данные были введены человеком, а не ботом или сценарием. Технология КАПЧА (CAPTCHA) - это один из способов убедиться, что мы имеем дело с человеком. Сейчас есть множество способов реализации КАПЧА, но здесь мы сосредоточимся на визуальном вводе данных капчи.

Реализация

Первая задача, которую необходимо решить, это сгенерировать изображение в классе капчи. Можно для этого использовать отдельную .aspx-форму, но тогда это не будет являться серверным контролом. Чтобы реально генерировать изображение "на лету", можно воспользоваться перехватчиком HttpHandler, который аккуратно решает эту задачу.

Все, что нам нужно, это немного измененить в Web.config раздел <system.web>:

<httpHandlers>
    <add verb="GET" path="CaptchaImage.aspx" 
       type="WebControlCaptcha.CaptchaImageHandler, WebControlCaptcha" />
</httpHandlers>

Этот обработчик определяет специальную страницу с именем CaptchaImage.aspx. В реале этой страницы не существует, однако когда прийдёт запрос к этой странице, то он будет перехвачен и обработан классом, включающим в себя интерфейс IHttpHandler: CaptchaImageHandler, как показано ниже:

Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) _
       Implements System.Web.IHttpHandler.ProcessRequest
    Dim app As HttpApplication = context.ApplicationInstance
 
    '-- получаем уникальный GUID капчи;
    '   он должен быть передан в запросе

    Dim strGuid As String = Convert.ToString(app.Request.QueryString("guid"))
 
    Dim ci As CaptchaImage
    If strGuid = "" Then
        '-- создаём картинку капчи с дефолтовыми настройками
        '-- в основном для процесса отладки кода 

        ci = New CaptchaImage
    Else
        '-- получаем капчу из кэша ASP.NET по GUID

        ci = CType(app.Context.Cache(strGuid), CaptchaImage)
        app.Context.Cache.Remove(strGuid)
    End If
 
    '-- записываем картинку в выходной HTTP-поток как массив байт

    ci.Image.Save(app.Context.Response.OutputStream, _
                              Drawing.Imaging.ImageFormat.Jpeg)
 
    '-- Указываем для браузера, что это картинка,
    '-- и указываем статус обработки запроса 200-Окей

    app.Response.ContentType = "image/jpeg"
    app.Response.StatusCode = 200
    app.Response.End()
 
End Sub

После выполнения этого кода, будет сгенерирована новая капча-картинка и отправлена в браузер прямо из памяти. Всё, проблема решена!

Однако, есть другая проблема. Должна быть связь между HttpHandler отвечающим за отображение картинки и веб-страницей контрола - в противном случае, как вызывающий контрол узнает, какой текст был сгенерирован в капче ? Если просмотреть исходный код сгенерированного контрола, то будет видно, что GUID передается в строке запроса:

<img src="CaptchaImage.aspx?guid=99fecb18-ba00-4b60-9783-37225179a704" 
     border='0'>

Этот GUID (глобальный уникальный идентификатор) является ключом, используемым для доступа к объекту CAPTCHA, который изначально был сохранён в кэше ASP.NET контролом. Давайте взглянем на метод CaptchaControl.GenerateNewCaptcha:

Private Sub GenerateNewCaptcha()
    LocalGuid = Guid.NewGuid.ToString
    If Not IsDesignMode Then
        HttpContext.Current.Cache.Add(LocalGuid, _captcha, Nothing, _
            DateTime.Now.AddSeconds(HttpContext.Current.Session.Timeout), _
            TimeSpan.Zero, Caching.CacheItemPriority.NotRemovable, Nothing)
    End If
    Me.CaptchaText = _captcha.Text
    Me.GeneratedAt = Now
End Sub

Этот код может показаться немного странным, тем не менее он прекрасно работает! Последовательность событий ASP.NET выглядит следующим образом:

1. Генерируется страница.
2. Страница вызывает CaptchaControl1.OnPreRender. При этом создаётся новый GUID и новый объект CAPTCHA со свойствами контрола. В результате объект CAPTCHA хранится в кэше по GUID.
3. Страница вызывает CaptchaControl1.Render; в браузер записывает тег < img > с урлом.
4. Браузер пытается получить объект указанный в урле тега < img >.
5. Возникает событие CaptchaImageHandler.ProcessRequest. Обработчик события извлекает GUID из строки запроса, объект капчи из кэша, и создаёт картинку капчи. Затем он удаляет объект из кэша. Обратите внимание, что в конце следует некоторый код очистки. Если по каким-то причинам, элемент управления сгенерирован, а картинка по урлу так и не была запрошена, то объект может остаться в кэше. Поэтому необходимо указать время жизни нашего объекта в кэше 20 минут.

Свойства CaptchaControl

CaptchaControl надлежащим образом реализует все дефолтовые свойства Серверного элемента управления ASP.NET, а также несколько собственных свойств:

Свойство Значение поумолчанию Описание
CacheStrategy HttpRuntime По соображениям безопасности, текст CAPTCHA никогда не передается клиенту, он будет храниться только на сервере. Он может быть сохранён в Сессии (Session) или HttpRuntime.
CaptchaBackgroundNoise Low Количество фонового шума, добавляемого в изображение капчи. Может принимать значения от None до Extreme.
CaptchaChars A-Z, 1-9 Символы из которых будет формироваться текст капчи. Символы выбираются из этой строки в случайном порядке. Поумолчанию не будут использованы некоторые символы, которые могут быть истолкованы двояко, такие как O, 0, I, 1, 8, B, и т.д.
CaptchaFont "" Шрифт, используемый при формировании текста капчи. Если значение не задано, то для каждого символа будет использован случайный шрифт. Список допустимых шрифтов уже встроен в контрол, чтобы предотвратить использование таких шрифтов как WingDings и т.д.
CaptchaFontWarping Low Уровень искажения каждого сивола текста. Может принимать значения от None до Extreme.
CaptchaHeight 50 Высота картинки в пикселях.
CaptchaLength 5 Длинна случайно генерируемого текста в символах.
CaptchaLineNoise None Количество "перечёркивающих" линий на картинке. Может принимать значения от None до Extreme.
CaptchaMaxTimeout 90 Количество секунд, которое капча-картинка будет оставаться в кэше, после того как она сгенерирована.
CaptchaMinTimeout 3 Минимально количество секунд, которое необходимо ждать пользователю перед вводом капчи.
CaptchaWidth 180 Ширина картинки в пикселях.
UserValidated False После постбэка возвращает True если пользователь ввёл правильно сгенерированный текст. Так же имеется стандартный интерфейс IValidation.
LayoutStyle Horizontal Определяет где будет расположено поле ввода: справа или снизу от картинки.

Постарайтесь настроить эти свойства с компромисом, чтобы с одной стороны программе оптического распознавания не удалось вычислить искажённый текст, а с другой - чтобы реальный человек смог пробиться через капчу! Для иллюстрации, посмотрите на две капчи:

CAPTCHA слева создается со всеми настройками "medium", что даёт разумный компромисс между визуальным восприятием человеком и читаемостью оптической распознавалки. CAPTCHA справа использует меньшее значение CaptchaFontWarping и меньшую длину CaptchaLength.

Скачать исходник для ASP.NET 2.0 - 14 кб

Скачать исходник для ASP.NET 1.1 - 22 кб




Основные разделы сайта


 

Реклама