HTML Decode/Encode.

Если кто-то слышал об такой атаке на веб-сайты, как XSS Injection, то он(она) знает что для предотвращение такой атаки необходимо использовать функции HtmlEncode/HtmlDecode. XSS Injection (Cross-site injection) - один из способов атак веб-приложений, главной идеей которого является вставка(инъекция) чужого javascript-кода на атакуемый веб-сайт. Как минимум, это может привести к краже печенек cookies и получении прав администратора сайта. ...

1.1. ASP.NET

Это происходит, примерно, так:
Допустим, у нас есть форма для отправки комментарием, где пользователь вводит свой еmail и текст коммеентария. Самый простой обработчик кнопки добавить окмментарий будет выглядить так:

protected void OnAddCommentClick(object sender, EventArgs e)
{
 var pageId = this.GetPageId();
 var email = this.txtEmail.Text;
 var comment = this.txtComment.Text;
 CommentsService.AddComment(pageId, email, comment);
}

С первой точки зрения этот код не содержит никаких ошибок, компилируется и корректно сохраняет данные в БД. Но, если в тексте  комментария будет любой HTML или JavaScript-код, то при отображении этого комментария на страницу без предварительной обработки мы увидем, что HTML и JavaScript-код без особых проблем обрабатываются браузером.
Таким образом, мы сделали наш сайт уязвимым и нарушили одно из базовых правил проектирования ПО: “Не доверять данным, которые пришли извне нашей системы”. От себя еще добавлю: вдвойне недоверять данным, которые были введенны пользователем. Чтобы исправить это ошибку, необходимо всего-лишь вызвать метод HttpServerUtility.HtmlEncode(), перед сохранением данных в базу:


 var email = Server.HtmlEncode(this.txtEmail.Text);
 var comment = Server.HtmlEncode(this.txtComment.Text);

После чего, строка вида “<script>alert(‘hello!’);</script>” будет сохранена в базу в таком виде:

 &lt;script&gt;alert(‘hello!’);&lt;/script&gt;

Теперь все хорошо: любой введенный пользователем текст не ламает нашу верстку и не вызывает выполнения стороннего javascript (пример 2).
Но все не так просто, как кажется. Теперь, если такой код вставить в обработчике OnAddPage(), где администратор сайта будет добавлять страницы, то вместо красивого текста пользователи увидят набор непонятных символов. Поэтому, при отображении содержимого страницы мы вызываем метод HttpServerUtility.HtmlDecode(), который переведет сохраненный в базе данных текст в такой вид, чтобы браузер его корректно обрабатывал.

Таким образом, мы избавили наш сайт от XSS Injection дали возможность пользователям воодить разнообразные данные без вреда для сайта.

Примечание. Во всех примерах выше свойство странице EnableRequestValidation было установлено в false для возможноти ввода символов “<“ и “>”.
Примечание для ASP.NET 4.0/ASP.NET MVC 2.0. В ASP.NET 4.0/ASP.NET MVC 2.0 появилась конструкция <%: ... %>, которая делает за нас HTML Decode/Encode.

1.2. JavaScript

Если нам необходимо реализовать данную функциональность на клиенте с помощью javascript, то нам на помощь приходит jQuery:

function htmlEncode(html) {
 return $('<div/>').text(html).html();
}
function htmlDecode(text) {
 return $('<div/>').html(text).text();
}

1.3 Python/Django

В фреймворке Django HTML Decode работает по умолчанию, и для его отключение в шаблоне (template) добавить блок {% autoescape off %} и в нем поместить все элементы, для которых нам не нужен HTML Decode, после чего закрыть блок с помощью {% endautoescape %}.

2. URL Decode/Encode.

В отличии от HTML Encode/Decode незаэкранированный url больших проблем не вызывает, за исключением двух моментов: url становится не таким простым и понятным для пользователя и это не очень хорошо влияет на SEO.

2.1 ASP.NET

Рассмотрим такую ситуацию: у нас есть сайт с функцией поиска по нем. Стандартная форма поиска содержит поле для вводи и кнопу "Поиск". В простейшем случае при нажатии на кнопку “Поиск” у нас есть такой обработчик:


protected void OnSerachClick(object sender, EventArgs e)
{
 var searchText = this.txtSearch.Text;
 car url = String.Format(“{0}?q={1}”, VirtualPathUtility.ToAbsoluteUrl(“~/Search.aspx”), searchText);
 Response.Redirect(url);
}

Вполне рабочий код, за исключением того, что в некоторых случаях в итоге мы получаем не очень красивый url вида:

/Search.aspx?q=some%20keywords

Конечно, такой url правильно обрабатывается браузером, но не всем пользователям будет понятно что он значит. Происходит это из-за того, что браузер автоматически заменяет символ пробела и ряд других символов на  их шестнадцатиричное значение вида %XX, где XX - код символа в шестнадцатиричной системе.
Сделано это было давно, кода браузеры были маленкими еще не умели отображать нелатинские символы в строке ввода адреса и для правильного отображения разнообразных символов.
И тут нам на помощь приходят методы HttpServerUtility.UrlEncode() и HttpServerUtility.UrlDecode() которые предназначены для переобразования параметров строки запроса в понятный для пользователей вид. Отдельно отчему, что эти методы предназначены для обработки исключительно параметров url, а для переобразования адреса к необходимому ресурсу существует метод HttpServerUtility.UrlPathEncode(), работа которого больше похожа на работу метода HttpServerUtility.HtmlEncode(), но учитывает все особенности построения url. Этот метод не имеет метода для обратного переобразования, но при правильном подходе к проектированию приложенич это не понадобится.

2.2. JavaScript

Аналог URL Encode в javascript - функция encodeURI()


В декабре прошлого года я написал пост по названием “Программирование на .NET: С чего начать?” на тему того, чтобы почитать начинающим разработчикам на платформе .NET. С того момента прошло достаточное количество времени и могло появиться желание или необходимость, начать писать веб-приложения на основе технологиеи ASP.NET. Не важно, будет это ASP.NET Webforms или ASP.NET MVC - в любом случаем, знание одной технологии не мешает познакомиться с другой. Далее я приведу список книг/блогов, которые рекомендую для знакомства с веб-разработкой на основе .NET Framework.

  • Начну с книги Дино Эспозито “Introducing Microsoft ASP.Net 2.0” - отличное введение в ASP.NET 2.0. Несмотря на то, что этот замечательный автор уже написал книгу по ASP.NET 3.5, эта книга не теряет соей актуальности и служит отличным введением в мир веб-разработки на основе технологий от Microsoft.
  • Книга “Programming Microsoft ASP.NET 3.5" является хорошим продлолжением предыдущей и не нуждается в комментариях. Добавлю лишь одно: некоторые считают что эти две книги все-равно что книга Дж. Рихтера CLR via C#.
  • Marco Bellinaso, “ASP.NET 2.0 Website Programming: Problem - Design - Solution” - книга, которая почетное место на моей книжной полке. Книга описывает процесс создания сайта под названием BeerHouse Project от начала и до конца. Если что-то непонятно, то всегда можно посмотреть исходники этого проекта. Отличная книга для начинающих, чтобы познакомиться с процессом создания сайта от начала и до конца.
  • Следующая книга от сразу двух авторов Matthew MacDonald и Adam Freeman имеет название “Pro ASP.NET 4 in C# 2010”. Я читал более старое название про ASP.NET 2.0. В книге достаточно подробно описывается технология ASP.NET, но читать ее нужно когда базовые знания уже есть.

Технология ASP.NET MVC более молодая и выбор книг значительно меньше. Большинство из них написаны про первую версию этого фреймворки и из-за значительных изменений настоятельно рекомендую читать книги по актуальной на сегодняшний день версии 2.0.
Это такие книги, как:

  • "Pro ASP.NET MVC 2 Framework" от Steven Sanderson - очень подробно и понятно написаны как основы, так и достаточно продвинутые вещи о ASP.NET MVC.
  • "ASP.NET MVC 2 in Action" ) от сразу пяти авторов. Если коротко, то я еще не встречал ни одной книги из этой серии, которая бы меня не заинтересовали и после прочтения которой я бы пожалел о потраченном времени.
  • Еще есть книга “ASP.NET MVC Framework” по ASP.NET MVC 2.0 от русских авторов Гайдара Магданурова и Владимира Юнева. Т.к. книгу только пролистал на балке, то никаких комметариев о ней писать не буду за исключением того, что она вполне годиться для введения в данную технологию.

С книгами закончили, теперь пройдемся по списку веб-ресурсов, RSS которых я регулярно читаю:

  • Сайт http://www.asp.net/ от Microsoft. Название говорит само за себя. Отличный ресурс с форумами, блогами, вики, ссылками на различные opensource приложения. Отдельно хочу выделить раздел с обучающим видео. Это лучше увидеть самому! Единственным их недостатком является то, что они могут ввести в ошибочное заблуждение, что разработка любого сайта - очень и очень простое занятие. В остальном - обязательно смотреть начинающим веб-разработчикам.
  • http://weblogs.asp.net/scottgu/ - блог Скота Гатри. Его должность решил не переводить, а процитировать с его блога:
    "My name is Scott Guthrie, and I am a Corporate Vice President in the Microsoft Developer Division. I run the development teams that build the following products/technologies: CLR and the core .NET Base Class Libraries, ASP.NET, Silverlight, WPF, IIS 7.0, Visual Studio Tools for ASP.NET, WPF, Silverlight and Mobile". Отличные технические посты о самых новых технологиях! Очень часто после публикации очередного поста проходит не одна неделя/месяц до того, как очередная технология/приложение станет доступным для разработчиков.
  • http://dev.net.ua/ и http://msug.vn.ua/ - сайты харьковской и винницкой .NET User Group - не только об asp.net, но и о других технологиях Microsoft.
  • http://www.nikhilk.net/ - Nikhil Kothari's Weblog - блог разработчика из Microsoft, посвященный веб-технологиям.
  • И последнее: MSDN - без него сложно представить жизь разработчика.

Продолжение следует. В следующем посте из серии для начинающих (веб)разработчиков я расскажу о том, что необходимо знать любому разработчику на платформе ASP.NET.


В связи с тем, что я повсеместно пытаюсь избавиться от ASP.NET AJAX Control Toolkit (ACT) и перейти на использование jQuery, то от использования Hover Extender от ACT пришлось отказаться. Сразу же было найдено большое количество разнообразных плагинов для jQuery, но большинство из них имели недостаточную реализацию, из-за чегоостановился на jQuery plugin EZPZ Tooltip.

Из основных достоинств данного плагина хочется выделить:

  • "Чистый" HTML - не нужно добавлять специальные атрибуты для элементов, плагин завязывается на отдельный HTML элемент.
  • Конфигурация через наименование (Convention over configuration) - поведение элементов зависит от из ID.
  • Гибкие настройки - с помощью CSS можно настроить как внешний вид контрола, так и его позиционирование.
  • Возможность замены стандартных эффектов путем перехвата соответствующих событий на jQuery.
  • Удобство и простота работы.
  • Маленький размер - 4.5K в сжатов виде.

Более подробно о всем этом можно почитать на странице проекта, а я хочу рассказать как можно его использовать в связке с ASP.NET на примере простого UserControl.

Для инициализации контрола нужно выполнить небольшой javascript:

$("#example-target-1").ezpz_tooltip();
или
$("#target").ezpz_tooltip({contentId:"content"}); - В случае если у наших HTML-элементов будут "нестандартные" для этого контрола ID.

Так как, ASP.NET сам генерирует нам ClientID элементов (я не учитываю специфику ASP.NET 4.0, где можно отключать автоматическую генерацию ClientID), то приходится использовать 2-й вариант таки образом:

 

При этом у нас:

  •  TargetControlId - ID элемента, при наведении на который будет отображаться наш hover (tooltip).
  • ContainerClientId - ID элемента который будет показываться в качестве hover (tooltip).

 Разметка нашего user control выглядит так:

 

Нам остаётся только разместить наш UserControl на странице и подключить необходимые стили и скрипты. Можно ещё сделать WebControl, но это уже зависит от конкретной задачи. В моём случае UserControl был предпочтительнее.

HoverControl.zip (31.35 kb)


DevConf 2010

Published 5/16/2010 by e0ne in Python | Web Development

DevConf 2010 уже завтра. До поезда в Москву осталось чуть более 3-х часов. Посмотрел финальную програму и немного расстроился: даже не смотря на то, что едем мы вдвоём, из-за плотного расспеисания и немкольких паралельных потоков врядли получится попасть на все интересующие доклады :(. Надеюсь что организаторы запишут и выложут видео.


Почему-то, всегда забываю синтаксис вызова script service/method. Руки так и тянуться написать:

var result = ScriptServiceExample.AsmxService.Hello;
или
var result = ScriptServiceExample.AsmxService.Hello();

И каждый раз, после написания такого когда приходится лезть в MSDN/Google чтобы понять почему же оно не работает. После прочтения документации становится понятно "как" нужно писать вызов метода, но вопрос "почему" ответ, как правило, находится не сразу. Чтобы понять почему же всё работает именно так, достаточно посмотреть JavaScript код, который генерируется службой. Посмотреть это можно зайдя по адресу http://localhost:65456/AsmxService.asmx/js и сохранив себе js-файл следующего содержания:

Type.registerNamespace('ScriptServiceExample');
ScriptServiceExample.AsmxService=function() {
ScriptServiceExample.AsmxService.initializeBase(this);
// ...
Hello:function(succeededCallback, failedCallback, userContext) {
return this._invoke(this._get_path(), 'Hello',false,{},succeededCallback,failedCallback,userContext); }}
// ...

С WFC AJAX-enabled службами всё работает также.

 

ScriptServiceExample.rar (7.44 kb)


ASP.NET + Mono + Apache

Published 9/22/2009 by e0ne in Mono | Web Development

Всё больше и больше можлно услышать о Mono. Как изестно, основное его идеей является реализация действительно кроссплатформенной среды .NET. Таким образом, чеще всего Mono испльзуют в операционной системе, отличной от MS Windows. А если не Windows, то Linux или какой-то из Unix. И всё было бы хорошо, если б не 2 момента (в данном случае я не акцентрирую внимание на степень готовности реализации Mono: аналог WinForms и замена Internet Information Services (IIS).На за мену WinForms приходят GTK, QTи другие библиотеки. А вот с заменой IIS все не тах хорошо: либо Apache с соответствующими модуляли, либо "родной" для Mono веб-сервер XSP2. А так как Apache наиболее популярен, то будем пользоваться им.

Все примеры я буду приводить для Ubuntu linux, но для других nix-подобных ОС все будет делаться таким же способом, за исключением установки пакетов.

Для начала нам все же надо установить Mono и IDE для нее. В качестве IDE  будем использовать MonoDevelop. Устанавливаем всё необходимое:

apt-get install mono-2.0-runtime mono-2.0-gac mono-2.0-service mono-2.0-devel mono-xsp2 mono-xsp2-base 

После чего можно запустить MonoDevelop, созать простое ASP.NET приложение и запустить. В результате получаем что-то похожее на это:

Теперь мы уже можем без проблем заниматься разработкой вплоть до момента, когда нужно запустить приложение на test-сервере, на которов, в качестве web-сервера, должен стоять Apache. Дело за малым - установить Apache и настроить его для работы с Mono.

Для наала, устанавливаем необходимы пакеты:

sudo apt-get install apache2 mono-apache-server2 libapache2-mod-mono

 

Говорим веб-серверу о необходимости загрузки нового модуля:

sudo a2enmod mod_mono

И создаём новый конфиг (/etc/mono-server2/monotest.webapp) для нашего приложения:

  <apps>
      <web-application>
         <name>Mono test</name>
         <vpath>/mono</vpath>
         <path>/var/www/</path>
        <vhost>localhost</vhost>
      </web-application>
</apps>


Последние что нас осталось сделать - это подправить конфигурационный файл Apache'а для нашего сайта (/etc/mono-server2/mono-server2-hosts.conf). Добавляем в него такие строки:

Alias /mono "/var/www"
AddMonoApplications default "/mono:/var/www"
    <Directory /var/www>
       SetHandler mono
          <IfModule mod_dir.c>
             DirectoryIndex Default.aspx
          </IfModule>
    </Directory>

Перезагружаем Apache командой:

sudo /etc/init.d/apache2 restart

И смотрим в браузере что у нас получилось:


Всё началось с того, что в спецификации к проекту написали примерно такое: "Время продолжительности сэссии пользователя на сайте должно составлять 120 минут". После чего, в web.config была добавлена следующая строка: 

<sessionState mode="InProc" cookieless="false" timeout="120" />

А на страницу был добавлен такой мета-тег:

<meta http-equiv="Refresh" content="7200; URL=/EzRc/Pages/LogOn/SessionExpired.aspx" />

Следует упомянуть конфигурацию тестовых серверов: Windows Vista/2008, IIS7, .NET 3.5. Ничто не предвещало беды. Но, как и полагается, в один "прекрасный" день всеми людимые QA написали баг следующего содержания: "Session expiration occurs prior to 30 min (and as little as 10 min)." При этом повторить его было достаточно просто:

  • залогиниться на сайт
  • оставить браузер в покое на 30 минут

После этих нетрудный манипуляций при попытке перейти по любой ссылке мы оказывались на странице, в которой радостно говорилось об окончании сэссии и предлагалось перейти на страницу логина. Естественно, этот баг повторялся не всегда.

Ещё раз убедившись в правильности настроек сэссии в web.config я реши воспроизвести этот баг на локальном (dev) компьютере. Как ни странно, но баг воспроизводился в 100% случаев. "Странно" - подумал я и налил ещё чашку кофе.

Запустив Fiddler2 и залогинившись на сайт я снова оставил его в покое на 30 минут. Через это время, убедившись, что cookie приходят валидные, я наал смотреть логи. Напервый взгляд всё было хорошо, но присмотревшись внимательно, увидел что отрабатывает событие ApplicationStart. Теперь понятно почему заканчивается сэссия. Осталось разобраться почему перезапускается приложение.

Из логов IIS:

Event code: 1002
Event message: Application is shutting down. Reason: Hosting environment is shutting down.
Event time: 6/8/2009 1:50:21 PM
Event time (UTC): 6/8/2009 10:50:21 AM
Event ID: 80d0faffb34547fea6299cfff8cf1c6f
Event sequence: 4
Event occurrence: 1
Event detail code: 50002
 
Application information:
    Application domain: /LM/W3SVC/1/ROOT/Web-1-128889305624881519
    Trust level: Full
    Application Virtual Path: /EzRc
    Application Path: C:\Src\Sites\Web\
    Machine name: localdev
 
Process information:
    Process ID: 6364
    Process name: w3wp.exe
    Account name: NT AUTHORITY\NETWORK SERVICE

 

 

После прочтения статьи из MSDN ASP.NET Application Life Cycle Overview ответ на интересующий вопрос не был получен, из чего был сделан вывод, что проблема находится уровне выше, а именно в IIS. Начал детально изучать настройки, которые могут повлиять на работу приложения и остановился на Application Pools. После чтения документации и нескольких неверных попыток был найден источник проблемы. Им оказался параметр Idle Time-out.

 



Оказалось, что при настройках по умолчанию, процесс, отвечающий за работу asp.net, тушится при условии, что к нему не обращаются в течении 20 минут. Это объясняло, почему проблему можно было не всегда воспроизвести на тестовом сервере.

Это же можно настроить и через файл machine.config. Подробнее описано здесь.


На днях столкнулся такой ситуацией, что многие некоторые разработчики при упоминании Ajax имеют в виду компонент UpdatePanel и не понимают как она работает. Сегодня я решил попытаться исправить эту ситуацию и рассказать что такое и как устроен ASP.NET Ajax.

 Для начала обратимся Википедии и посмотрим, что такое Ajax:

AJAX (Asynchronous Javascript and XML — «асинхронный JavaScript и XML») — это подход к построению интерактивных пользовательских интерфейсов веб-приложений, заключающийся в «фоновом» обмене данными браузера с веб-сервером. В результате при обновлении данных веб-страница не перезагружается полностью, и веб-приложения становятся более быстрыми и удобными.

Для выполнения асинхронных запросов, на JavaSctipt необходимо создать объект XMLHttpRequest, который и будет взаимодействовать с сервером. В зависимости от браузера, объект создаётся разными способами, но можно написать универсальный метод для его создания:

    function createRequestObject()
    {
    if (window.XMLHttpRequest) {
    try {
    return new XMLHttpRequest();
    } catch (e){}
    } else if (window.ActiveXObject) {
    try {
    return new ActiveXObject('Msxml2.XMLHTTP');
    } catch (e){
    try {
    return new ActiveXObject('Microsoft.XMLHTTP');
    } catch (e){}
    }
    }
    return null;
    }
 

 

Теперь вернёмся в ASP.NET. Как несложно догадаться, Microsoft ASP.NET Ajax имееит клиент-серверную архитектуру:

Серверная часть Microsoft ASP.NET Ajax отвечает за авторизацию и аутентификацию пользователей, генерацию и регистрацию на странице необходимых скриптов, имеет всё необходимое для работы с веб-службами, включая генерацию proxy-классов, xml и JavaScript сериализацию. Также доступно несколько компонентов (ScriptManager, UpdatePanel, UpdateProgress и Timer), которых вполне достаточно для реализации базовых функций.

Клиентская часть имеет название Microsoft AJAX Library и состоит из нескольких JavaScript файлов, с помощью каких взаимодействие с сервером становится проще. В этой библиотеке доступно множество классов, для взаимодействия с веб-службами, работы с DOM-моделью браузера, имебтся базовые классы для создания собственных контролов.

В следующих постах я расскажу подробнее о том, как работает серверная часть и загляну внутрь Microsoft AJAX Library.

Ссылки, где можно почитать подробнее об ASP.NET AJAX:


Уже немала было написано на эту тему, но в статье http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx пошли немного дальше: теперь url rewriting настроен таким образом, что нет необходимости в имени контроллера в пути прописывать расширение. Не буду утверждать что это что-то новое, но я до этого использовал пути вроде http://localhost/mvcsite/home.mvc.


В предыдущем посте я рассказал как подружить Visual Studio и IronPython. Сегодня мы напишем первое приложение на ASP.NET на языке IronPython.

Для начала необходимо скачать ASP.NET Dynamic Language Support, который включает в себя документацию и два примера: ASP.NET MVC IronPython Sample и ASP.NET Webforms IronPython Sample. Webforms sample- это обычный web site проект с такими файлами:

 

 К сожалению, в текущей версии не поддердивается проект Web Application.

C ASP.NET MVC Sample всё на много интереснее. Т.к. Python - это динамичский язык и не поддерживает атрибутов, то код контроллеров приходится писать на C#. С model и view всё значитально проще. Можно использовать IronPython, только во view нужно указать Language="IronPython". В остальном создание приложение ничем не отличается от такового на C#.

Ну и напоследок хочу сказать, что на прошлой неделе вышел IronPython 2.0 Release Candidate 1.

Продолжение следует.


e0ne's comments

A Web Developer's Blog!