Что такое код asp appisolated

Содержание

Транзакции

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

Например, рассмотрим транзакцию, которая передает $1000 со счета A на счет B. Ясно, что здесь присутствует две операции:

снять $1000 со счета А;

добавить $1000 на счет B.

Предположим, что приложение успешно выполнило шаг 1, но из-за какой-то ошибки шаг 2 завершился сбоем. Это ведет к несогласованию данных, поскольку общая сумма денег в системе теперь не точна. Пропало $1000.

Транзакции позволяют избежать проблем подобного рода, поскольку гарантируют, что изменения будут зафиксированы в источнике данных только в том случае, если все шаги пройдут успешно. Поэтому в рассматриваемом примере, если шаг 2 сорвется, то изменения, выполненные на шаге 1, не будут зафиксированы в базе данных. Это гарантирует, что система останется в одном из двух корректных состояний — начальном (когда деньги не переведены) или конечном (когда деньги дебетованы с одного счета и кредитованы на другой).

Транзакции характеризуются четырьмя свойствами, которые называются свойствами ACID. Здесь ACID представляет перечисленные ниже концепции:

Атомарность (Atomic)

Все шаги транзакции должны либо выполниться успешно, либо отмениться. Если не все шаги транзакции завершены, она не трактуется как завершенная.

Согласованность (Consistent)

Транзакция переводит лежащую в основе базу данных из одного стабильного состояния в другое.

Изолированность (Isolated)

Каждая транзакция — независимая сущность. Одна транзакция не должна влиять на другие, запущенные одновременно с ней.

Устойчивость (Durable)

Изменения, которые происходят во время транзакции, сохраняются постоянно на каком-то носителе (обычно на жестком диске), прежде чем транзакция будет объявлена успешной. Поддерживается ведение журналов, чтобы база данных могла быть восстановлена в корректное состояние, даже в случае сбоя оборудования или сети.

Обратите внимание, что эти идеальные характеристики транзакции не всегда полностью достижимы. Одна из проблем связана с обеспечением изоляции. Реляционная СУБД должна блокировать данные, чтобы другие пользователи не имели к ним доступа, пока транзакция выполняется. Чем больше используется блокировок, и чем они крупнее, тем выше шансы того, что пользователь не сможет выполнить другую работу, пока транзакция находится в процессе выполнения. Другими словами, иногда приходится идти на компромисс между степенью параллелизма работы пользователей и изоляцией.

Транзакции и приложения ASP.NET

В приложениях ASP.NET можно использовать три базовых типа транзакций. Ниже представлен их список (от наименее до наиболее затратных):

Транзакции хранимых процедур. Эти транзакции происходят целиком в базе данных. Транзакции хранимых процедур обеспечивают наилучшую производительность, поскольку требуют всего одного обращения к базе данных. Недостаток состоит в том, что приходится писать всю логику транзакции с использованием операторов SQL.

Инициированные клиентом (ADO.NET) транзакции. Эти транзакции управляются программно кодом вашей веб-страницы ASP.NET. «За кулисами» они применяют те же команды, что и транзакции хранимых процедур, но код использует ряд объектов ADO.NET, которые скрывают детали. Недостатком является необходимость в нескольких обращениях к базе данных, чтобы запустить и зафиксировать транзакцию.

Транзакции COM+. Эти транзакции обрабатываются исполняющей средой COM+ на основе декларативных атрибутов, добавленных вами в код. Транзакции COM+ используют протокол двухфазной фиксации и всегда подразумевают наличие дополнительных накладных расходов. Они требуют создания отдельного класса служебного компонента.

В общем объекты COM+ хороший выбор только в том случае, если транзакция охватывает несколько транзакционных диспетчеров ресурсов, поскольку COM+ включает встроенную поддержку распределенных транзакций. Например, отдельная транзакция COM+ может охватывать взаимодействие с базой SQL Server и базой Oracle.

Несмотря на то что ADO.NET предоставляет хорошую поддержку транзакций, вы не всегда должны их использовать. Фактически всякий раз, когда применяется какого-то рода транзакция, автоматически привносятся накладные расходы. К тому же транзакции предполагают некоторого рода блокировку строк таблицы. Поэтому транзакции, используемые без необходимости, могут нанести ущерб масштабируемости приложения.

Чтобы достичь наилучшего результата, при реализации транзакций нужно следовать перечисленным ниже рекомендациям:

Сохраняйте транзакции насколько возможно короткими.

Избегайте возврата данных запросом SELECT посреди транзакции. В идеале вы должны вернуть данные перед запуском транзакции. Это сократит объем данных, заблокированных транзакцией.

Если вы извлекаете записи, то извлекайте только те строки, которые необходимы, чтобы сократить количество блокировок.

Где только возможно, реализуйте транзакции внутри хранимых процедур, а не используйте транзакции ADO.NET. В результате транзакции будут стартовать и завершаться быстрее, т.к. серверу базы данных не придется взаимодействовать с клиентом (веб-приложением).

Избегайте транзакций, которые комбинируют множество независимых пакетов работы. Помещайте отдельные пакеты в отдельные транзакции.

По возможности избегайте обновлений, которые затрагивают большое количество записей.

В ADO.NET также поддерживается высокоуровневая модель распространяемых транзакций. Однако распространяемая транзакция — это не какой-то новый тип транзакции, а просто способ создания инициируемой клиентом транзакции, которая при необходимости может автоматически расширяться до транзакции COM+. Вы не должны использовать распространяемые транзакции, если только действительно в них не нуждаетесь, потому что трудно предсказать их влияние на производительность и масштабируемость окончательных решений.

Запомните эмпирическое правило: применяйте транзакции только тогда, когда операция того требует. Например, если вы просто выбираете записи из базы данных либо инициируете запрос, то транзакции не нужны. С другой стороны, если вы вставляете запись Order, которая связана с последовательностью зависимых записей OrderItem, то транзакция может понадобиться. Вообще транзакции никогда не требуются для одиночных команд, таких как индивидуальные операторы UPDATE, DELETE или INSERT, поскольку они по определению транзакционны.

Транзакции хранимых процедур

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

Это также гарантирует максимально возможную производительность, поскольку все действия могут быть выполнены на источнике данных, без потребности в каком-либо сетевом взаимодействии. В общем случае, чем короче промежуток времени транзакции, тем выше степень параллелизма базы данных и меньше количество запросов, которые будут сериализоваться (ожидающих, пока существует временная блокировка записей).

Код хранимых процедур варьируется в зависимости от используемой базы данных, но большинство реляционных СУБД поддерживают SQL-оператор BEGIN TRANSACTION. После запуска транзакции все последующие операторы рассматриваются как ее часть. Завершается транзакция с помощью оператора COMMIT или ROLLBACK. Если этого не сделать, транзакция будет автоматически отменена.

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

В приведенном примере применяются средства ограниченной обработки ошибок Transact-SQL (вариант SQL, реализованный в SQL Server). При использовании значения @@ERROR в Transact-SQL следует соблюдать осторожность и проверять его немедленно после каждой операции. Это связано с тем, что @@ERROR сбрасывается в 0 при успешном завершении оператора SQL. В результате, если первое обновление потерпит неудачу, а второе выполнится успешно, @@ERROR вернет 0. В этой точке проверять его уже слишком поздно.

Инициированные клиентом транзакции ADO.NET

Большинство поставщиков данных ADO.NET включают поддержку баз данных. Транзакции стартуют через объект Connection вызовом метода BeginTransaction(). Этот метод возвращает специфичный для поставщика объект Transaction, используемый для управления транзакцией. Все классы Transaction реализуют интерфейс IDbTransaction. Поставщики включают классы наподобие SqlTransaction, OleDbTransaction, OracleTransaction и т.д. реализующие этот интерфейс.

Класс Transaction предоставляет два ключевых метода:

Этот метод указывает завершение транзакции и помещение выполненных изменений в источнике данных.

Этот метод указывает отмену транзакции. Неоконченные изменения отменяются, и состояние базы остается прежним.

Обычно метод Commit() используется в конце операции. Однако если в процессе возникнет любое исключение, должен быть вызван Rollback(). Рассмотрим пример вставки двух записей в таблицу Employees:

Обратите внимание, что просто создать и зафиксировать транзакцию недостаточно. Также необходимо явно включить каждый объект Command в состав транзакции, установив значение их свойства Command.Transaction равным объекту Transaction. Если вы попытаетесь выполнить команду, которая не является частью текущей транзакции, пока транзакция находится в процессе выполнения, то получите ошибку. Однако в будущем эта объектная модель может разрешить поддержку более одной транзакции одновременно в пределах одного соединения.

Вместо использования отдельных объектов команд можно также выполнить один и тот же объект дважды, просто по ходу модифицируя его свойство CommandText (если это динамический оператор SQL) или значения его параметров (если это параметризованная команда). Например, если команда вставляет новую запись, такой подход можно применить для вставки двух записей в одной транзакции.

Чтобы протестировать свойство отката (отмены) транзакции, вставьте следующую строку непосредственно перед вызовом метода Commit() в предыдущем примере:

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

Хотя транзакции ADO.NET вращаются вокруг объектов Command и Transaction, лежащие в основе команды не отличаются от тех, что применяются в транзакциях хранимых процедур. Например, когда вызывается метод BeginTransaction() с поставщиком данных SQL Server, он отправляет базе данных команду BEGIN TRANSACTION.

Транзакция должна быть завершена как можно скорее (запущена как можно позже и завершена как можно раньше). К тому же активная транзакция блокирует различные задействованные ресурсы, поэтому следует выбирать только те строки таблиц, которые действительно необходимы.

Уровни изоляции

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

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

Исключительные блокировки — это блокировки, которые предотвращают одновременную модификацию данных двумя или более транзакциями. Исключительная блокировка устанавливается, когда транзакция собирается обновить данные, и никакой другой блокировки на этот момент не установлен. Ни один другой пользователь не сможет модифицировать данные, пока на них установлена исключительная блокировка.

В SQL Server на самом деле поддерживается несколько типов блокировок, работающих совместно, чтобы предотвратить взаимные блокировки и другие неприятные ситуации. За дополнительной информацией о блокировках обращайтесь в руководство SQL Server Books Online Help, которое устанавливается вместе с SQL Server.

В хранимых процедурах SQL Server можно устанавливать уровни изоляции, используя команду SET TRANSACTION ISOLATION LEVEL. В ADO.NET можно передать значение перечисления IsolationLevel перегруженному методу Connection.BeginTransaction(). В таблице ниже показаны его возможные значения:

Значения перечисления IsolationLevel

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

Разделяемые блокировки удерживаются, пока данные читаются транзакцией. Это исключает случаи недействительного чтения, но данные могут быть изменены до завершения транзакции. Это может привести к невоспроизводимым чтениям или фантомным записям. Этот уровень изоляции в SQL Server используется по умолчанию

Сохраняет копию данных, к которым обращается транзакция. В результате транзакция не может видеть изменений, выполненных другими транзакциями. Этот подход ограничивает блокировки, поскольку даже если другие транзакции удерживают блокировки на этих данных, транзакция с таким уровнем изоляции будет способна читать копии данных. Этот уровень изоляции поддерживается только в SQL Server 2005 и последующих версиях и должен быть включен через параметр уровня базы данных

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

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

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

Грязное чтение (dirty read)

Грязное чтение — это чтение, имеющее дело со значением из другой незавершенной транзакции, которая позже может быть отменена.

Невоспроизводимое чтение (unrepeatable read)

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

Фантомная строка (phantom row)

Фантомная строка — это строка, которая не появляется при начальном чтении, но появляется, когда те же данные читаются вновь в той же транзакции. Это может произойти, если другой пользователь вставляет запись до завершения вашей транзакции. Чтобы предотвратить появление фантомных строк, когда ваша транзакция выполняет запрос, сервер базы данных должен применять блокировку диапазона на основе конструкции WHERE этого запроса.

Будут эти феномены безобидными причудами или потенциальными источниками ошибок — зависит от специфических требований. Большую часть времени невоспроизводимые чтения и фантомные строки не представляют собой серьезных проблем, а усилия по их предотвращению слишком дорогостоящи, чтобы имело смысл их предпринимать. Однако если вам нужно обновлять множество строк сразу, и эти строки содержат некоторые взаимосвязанные данные, может понадобиться более строгая блокировка, чтобы предотвратить перекрывающиеся изменения, чреватые нарушением согласованности данных.

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

Значение Описание
ReadUncommitted
ReadCommitted
RepeatableRead
Serializable
Сравнение уровней изоляции транзакций

Уровень изоляции Грязное чтение Невоспроизводимое чтение Фантомные данные Параллелизм (несколько пользователей)
ReadUncommitted Да Да Да Наилучший
ReadCommitted Нет Да Да Хороший
Snapshot Нет Нет Нет Хороший
RepeatableRead Нет Нет Да Слабый
Serializable Нет Нет Нет Очень слабый

Точки сохранения

Всякий раз, когда производится откат транзакции, аннулируются результаты всех команд, выполненных с момента старта транзакции. Но как быть, если вы хотите откатить только часть текущей транзакции? В SQL Server для этого предназначено средство, которое называется точками сохранения (savepoints).

Точки сохранения — это метки, которые работают подобно книжным закладкам. Вы отмечаете определенную точку в потоке транзакции, и затем можете выполнять ее откат до этой точки. Точка сохранения устанавливается с помощью метода Transaction. Save(). Обратите внимание, что метод Save() доступен только в классе SqlTransaction, поскольку не является частью стандартного интерфейса IDbTransaction.

Ниже демонстрируется концепция использования точки сохранения:

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

Что такое код asp appisolated

ASP – веб-технология, которую в декабре 1996 года представила компания Microsoft для возможности создания интерактивных веб-приложений. ASP – это аббревиатура от Active Server Pages, что переводится, в соответствии с логикой технологии, как «активные серверные страницы». Важно понимать, что ASP не является языком программирования, она только позволяет встраивать в обычный HTML-код сценарии на каком-либо скриптовом языке(Visual Basic Script или Java Script). Таким образом, за счет использования ASP на веб-страницы могут встраиваться элементы с заранее настроенным программным управлением.

Изначально в любом текстовом редакторе создается исходный код программы. По умолчанию используется Visual Basic – если ничего дополнительно не указывать, система будет считать, что программа написана именно на этом языке. Затем файл, которому задается расширение .asp, выкладывается в каталог, имеющий права на выполнение, чтобы сервер мог исполнить этот файл, когда браузер пользователя запросит его. Для пользователя этот файл не виден, поскольку сначала загруженный файл с программой интерпретирует сервер таким образом, что программный код будет отображаться непосредственно в HTML-коде страницы, в скобках вида скобки .

ASP просуществовала в чистом виде до 2002 года. 1 января этого года увидел свет релиз ASP.NET, технологии, в которой были учтены ошибки и недочеты ASP. Устранить их получилось благодаря тому, что новая технология была основана на более функциональной платформе Microsoft .NET.

Синонимы: нет
Все термины на букву «A»
Все термины в глоссарии

Диагностика и индикаторы состояния работы точек UniFi AP

Диагностика и индикаторы состояния работы точек UniFi AP

В функционировании системы UniFi могут возникать различные неисправности:

  • Потеря питания или кабельного подключения точками доступа.
  • Логическое нарушение соединения точек доступа и контроллера в режиме L3 подключения.
  • Не запускается контроллер UniFi.

Потеря питания или кабельного подключения отслеживаются по сообщению в Alerts и подсвечиванию точки доступа красным цветом на карте.

Состояния точек доступа UniFi:

Состояние точки доступа

Возможные причины
состояния

Рекомендуемые действия

Зеленый
индикатор
горит
постоянно

Точка доступа успешно подключена к контроллеру

Штатный режим
функционирования, действия не требуются

Зеленый
индикатор
горит
постоянно

Точка доступа успешно подключена на ней
выполняется обновление ПО или настроек соответственно

Штатный режим
функционирования, действия не требуются

Оранжевый
индикатор
горит
постоянно

Точка доступа подключается к контроллеру

Действия не требуются

Оранжевый
индикатор
горит
постоянно

Точка доступа обнаружена
контроллером

Можно подключить точку
доступа adoption

Managed by
other

Точка доступа настроена для работы с другим контроллером

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

Периодически
мигает
зеленый
индикатор

Невозможность пропинговать адрес Сonnectivity Monitor.
Связь с контроллером при этом присутствует, но точка доступа не обслуживает Wi-Fi клиентов.

Проверить состояние узла, используемого в качестве
Сonnectivity Monitor. Eсли
проблема возникла на одной части точек доступа, то проверить сетевые настройки коммутаторов — разрешен ли доступ из этой подсети к узлу Сonnectivity Monitor.

Оранжевый
индикатор
горит
постоянно

Потеряна связь точки доступа с контроллером

Кратковременно данное
состояние может быть вызвано перезагрузкой точки после обновления ПО или конфигурации.
Проверить наличие питания на точке доступа, ее исправность, подключение ethemet кабеля, разрешен ли доступ из этой подсети к контроллеру.

Проблемы логического взаимодействия точек доступа с контроллером из другой подсети возникают из-за невозможности точки найти контроллер. В этом случае проверьте следующие параметры сети:

  • Совпадает ли VLAN, в котором находится контроллер, с VLAN точек доступа, не тегирован ли он?
  • Корректно ли работает маршрутизация между подсетями точек доступа и контроллера?
  • Как точка доступа должна находить контроллер в другой подсети (DHCP option 43, DNS, с помощью утилиты)?
  • Не фильтруются ли необходимые для работы контроллера порты между подсетями?

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

Крайне нежелательно запускать контроллер UniFi из-под учетной записи, содержащей кириллические символы. Если ваше имя пользователя в ОС Windows на русском языке, создайте пользователя на английском языке, залогинтесь под ним и выполняйте установку от этого пользователя.

Для работы UniFi контроллера должны быть открыты следующие порты:

  • TCP 8080
  • TCP 8443
  • TCP 8880
  • TCP 8843
  • TCP 22
  • UDP 3478

При запуске контроллера UniFi проверяется доступность портов, и выводится сообщение, если какой-либо из портов занят. Также данную информацию можно посмотреть в логах в файле C:\Documents and Settings\user\Ubiquiti UniFi\logs\server.log

Если порт занят, остановите контроллер и в файле C:\Documents and Settings\user\Ubiquiti UniFi\data\system.properties измените данный порт на любой неиспользуемый.

Нашли ошибку в тексте? Выделите фрагмент текста и нажмите Ctrl+Enter

Что такое код asp appisolated

Этот текст предназначен для тех, кто никогда не имел дела с ASP и вообще смутно себе представляет возможности программирования на стороне сервера. Я ставил себе задачу создать у читателя общее представление о предмете. Отдельные неточности при этом менее важны — пожалуйста, громко не ругайтесь.

Общие сведения

ASP (Active Server Pages) – это мощная технология от Microsoft, позволяющая легко разрабатывать приложения для WWW. ASP работает на платформе Windows NT и IIS (Internet Information Server), начиная с версии 3, хотя вроде есть реализации на других платформах. ASP – это не язык программирования, это внутренняя технология, позволяющая подключать программы к Web-страницам. Основа успеха ASP – простой скриптовый язык (Visual Basic Script или Java Script) и возможность использования внешних COM-компонент.

Как это все происходит?

Вы пишете программу и складываете в файл на сервере. Браузер клиента запрашивает файл. Файл сначала интерпретируется сервером, на выходе производится HTML-код. Этот HTML посылается клиенту. Файлы с программами имеют расширение .asp. Файлы asp – это обычные текстовые файлы, содержащие исходные тексты программ. Файлы делаются с помощью любого текстового редактора. Каталог, в котором размещены файлы asp должен иметь права на выполнение, так как сервер исполняет эти файлы, когда браузер их запрашивает. Собственно программы пишутся на любом скриптовом языке, который установлен в системе. По умолчанию поддерживаются VBScript и JavaScript. Можно доустановить другие (например, Perl). Если ничего специально не указывать используется VBScript. В дальнейшем будем ссылаться только на него. Программные фрагменты заключаются в скобки . Можно ставить открывающую скобку в начале файла, закрывающую – в конце, все что между ними – программа на Visual Basic’е.

Какие средства есть для программирования?

Web – нормальная среда программирования, если правильно понять, что есть что. В VBScript есть все нормальные конструкции структурного программирования (if, while, case, etc). Есть переменные (описывать не обязательно, тип явно не задается). Поддерживаются объекты. Работа с ними обычная – Object.Property, Object.Method. Есть ряд встроенных объектов (Request, Response, Session, Server, Connection, Recordset). Можно доустанавливать другие компоненты (скачивать, покупать, программировать), например для работы с электронной почтой.

Вывод

Понятия «экран», куда можно выводить данные нет. Все, что надо показать пользователю, выбрасывается в выходной поток на языке HTML. Браузер пользователя интерпретирует этот HTML. Для упрощения вывода существует объект Response . Вывод осуществляется с помощью метода Write .

Так производится запись во внутренний буфер объекта Response. Когда скрипт заканчивает работу, весь буфер выдается клиенту. Надо заметить, что клиент получает «чистый» HTML, таким образом программы на ASP не зависят от клиентского ПО, что очень важно. Если внутри выводимой строки нужно использовать кавычку, кавычка удваивается. Другие методы и свойства Response позволяют управлять выводом. Так Response.Buffer регулирует, получает ли клиент данные по мере из записи в Response, или все сразу по завершении исполнения страницы. Метод Response.Redirect перенаправляет браузер на другую страницу. Чтобы им пользоваться, нельзя до него на странице использовать Response.Write.

Программа на ASP не может явно спросить пользователя о чем-то. Она получает данные из других страниц, либо через URL. Передаваемые параметры помещаются во входной поток и доступны через объект Request . Чтобы передать переменную var в программу test.asp , надо написать:

Чтобы из программы получить значение этой переменной, надо написать:

Несколько переменных разделяется знаком &:

Кроме того, чтобы задавать параметры в URL, можно воспользоваться формами HTML. В вызывающей странице пишем так:

Так это выглядит:

При этом пользователь увидит форму из одного поля ввода (var1), в нем будет значение по умолчанию «default». Второе поле (var2) будет невидимо и будет передавать всегда фиксированное значение «var2value». Кнопка «Submit Form» завершает заполнение формы и передает все переменные на test.asp (action). Если method=»get», переменные передаются через URL (test.asp?var1=default&var2=var2value). Если method=»post», передаются вместе с запросом так, что внешне передача переменных не заметна. В вызываемой программе безразлично, какой метод изпользовался (почти). Если у вас нет специальных аргументов за метод GET, используйте метод POST.

Формы

Формы HTML используются для организации диалога с пользователем. Поддерживаются стандартные элементы управления. Все многообразие задается немногими тэгами:

  • INPUT (с параметром TYPE=)
  • SELECT
  • TEXTAREA

Описание – в документации по HTML.

Взаимосвязь между отдельными страницами

Обычно сервер WWW не хранит состояние приложения, т.е. все запросы взаимонезависимы, и нет стандартного способа понять, что несколько запросов пришли от одного и того же пользователя. Но это очень нужно для разработки полноценных приложений и является одной из главных проблем разработки Web-приложений.

Один из методов решения этой проблемы — cookies . Пользователю при первом обращении выдается специальный идентификатор, после этого браузер пользователя предъявляет этот идентификатор при каждом обращении, и сервер может распознать, что это тот же самый пользователь. Пользователь может отключить cookies, в этом случае этот метод не работает.

ASP, используя cookies, предоставляет программисту более простое средство — объект Session (сессия). Сессия стартует, когда новый пользователь обращается к любому asp-файлу приложения. Сессия заканчивается при отсутствии активности пользователя в течение 20 минут, либо по явной команде. Специальный объект Session хранит состояние сессии. Туда можно записывать переменные, которые доступны из любой страницы в этой сессии. Записать данные в этот объект можно просто:

Считать потом еще проще:

Сессия, таким образом, – это еще один метод передачи данных между страницами. Одна страница пишет данные в сессию, другая – берет потом оттуда.

Наряду с объектом Session существует объект Application . Если сессия создается для каждого нового пользователя, до Application существует в единственном экземпляре, и может использоваться всеми страницами приложения.

Управление приложением

Программисту предоставляется возможность реагировать на 4 события: старт/стоп приложения и старт/стоп каждой сессии. Для реализации этих событий предназначен файл global.asa , который должен располагаться в корневом каталоге приложения. Вот его примерный скелет:

Нужно «просто» вписать Ваш код на соответствующее место. Нужно заметить, что отлаживать код для global.asa довольно непросто, так как он выполняется при очень специфических обстоятельствах (к примеру при старте или остановке сервера).

Использование внешних компонент

Если на сервере установлены дополнительные компоненты, их можно использовать из ASP. Стандартные объекты (например из библиотек ADO (Connection и Recordset) и Scripting (Dictionary, FileSystemObject)) доступны всегда. Установка новой компоненты обычно состоит в копировании dll-файла в каталог на сервере и ее регистрации с помощью программы regsvr32.exe. [В COM+ используется своя процедура инсталляции объектов, это однако не влияет на использования объектов.]

Создать экземпляр объекта можно так:

Class.Object указываются в документации на компоненту. В переменной var запоминается ссылка на созданный экземпляр объекта. Когда объект не нужен, ссылку нужно обнулить с помощью команды:

Пожалуйста всегда обнуляйте все ссылки на объекты, когда они больше не нужны. Теоретически это должно происходить автоматически при завершении процедуры/страницы, однако в стандартной сборке мусора есть определенные «проблемы».

В остальном использование компоненты зависит от самой этой компоненты.

Работа с базами данных

Из ASP можно легко и просто работать с любыми базами данных. Это делается через две промежуточные технологии: ODBC и ADO.

ODBC позволяет организовать доступ к любым базам данных через унифицированный интерфейс с помощью языка SQL. Специфика конкретных СУБД учитывается при помощи специальных драйверов БД. Такие драйверы существуют для всевозможных СУБД (в частности SQL Server, Oracle, Access, FoxPro). Поддержка ODBC обеспечивается на уровне операционной системы Windows (NT). Настройка – через Control Panel/ODBC. Базовым понятием является источник данных или data source. Источник данных – это совокупность сведений о базе данных, включая ее драйвер, имя компьютера и файла, параметры. Чтобы пользоваться базой надо создать источник данных для нее. Важно, чтобы источник данных был «системным», в отличии от «пользовательского». После этого надо лишь знать имя источника данных. [В настоящее время ODBC отступает перед натиском технологии OLE DB. На практике это однако практически ничего не изменяет. Вместо имени источника данных нужно использовать Connection String, в которой указывается имя ODBC-драйвера и все его параметры.]

ADO – это совокупность объектов, доступных из ASP, позволяющих обращаться к источнику данных ODBC [или OLE DB]. Фактически нужны лишь 2 объекта – Connection , представляющий соединение с базой данных и Recordset , представляющий набор записей, полученный от источника. Сначала необходимо открыть соединение, потом к нему привязать Recordset, потом, пользуясь методами Recordset’а, обрабатывать данные. Вот пример:

Если команда SQL не возвращает данных, recordset не нужен, надо пользоваться методом Conn. Execute (SQL_COMMAND).

Если Вы хотите вызывать хранимые процедуры сервера БД с параметрами, нужно воспользоваться объектом Command , который в свою очеред содержит объекты Parameter .

Методики программирования, советы


Описание переменных

VBScript — очень нетребовательный к программисту язык. Так он не требует описывать переменные и не содержит явных типов данных. Все переменные принадлежат одному типу Variant . Из-за отсутствия описаний могут произойти очень трудно обнаруживаемые ошибки. Одна опечатка может стоить полдня поисков.

Однако, есть возможность явно потребовать описания переменных. Для этого первой строкой в ASP-файле нужно написать Option Explicit . После этого обращение к переменной, которая не была объявлена с помощью Dim , вызывает ошибку с указанием номера строки.

Кстати, где расположены описания Dim в процедуре — совершенно не важно. Они могут стоять как до использования переменной, так и после, и даже в цикле. Видимо они отрабатываются препроцессором. Явно задать тип переменной с помощью Dim Var as Typ , как в Visual Basic, все равно нельзя.

Чередование ASP/HTML

Если нужно выдать большой кусок HTML, можно не пользоваться Response.Write. Если в asp-файле встречается кусок текста вне скобок , он трактуется просто как HTML, который надо вывести. Пример:

Обработка ошибок

Для отслеживания ошибок используется специальный объект Err . Он устанавливается в ненулевое значение, если предыдущая команда породила ошибку. Ее можно проверять с помощью If, и таким образом реагировать на ошибки. Чтобы из-за ошибки не прерывалось выполнение программы, в начале нужно включить команду

Включение других файлов

Можно выносить повторяющийся код в отдельный файл, и подключать к разным другим по мере необходимости с помощью команды include . Это очень удобно, если вы хотите вынести повторяющийся код в отдельный файл и использовать снова и снова в разных страницах:

Важно: все includes в тексте отрабатываются до исполнения файла. Т.е. даже если include стоит внутри if, то сначала будут включены все includes во всех ветках, и только потом, во время исполнения, будет принятно решение, какую ветку выполнять. Т.е. следующий код не дает условного включения файлов:

Обработка форм

Если надо что-то спросить у пользователя и на основании этого что-то сделать, в простейшем случае создается два файла: один с формой, второй – с ее обработчиком. Обработчик выполняет все действия. Пример:

Рекурсивная обработка форм

Удобный метод состоит в том, чтобы сбор данных и обработку осуществлял один и тот же файл. Для этого пишется asp, в котором есть разные разделы. Специальная переменная отвечает за выбор раздела при запуске. Пример:

Переменные HTTP

Запрос от браузера, кроме запрашиваемой страницы несет еще некоторые данные. Эти данные, например, IP-адрес клиента, доступны через специальные переменные объекта Request. IP-адрес – Request(«REMOTE_ADDR»). Другие — см.документацию (ASPSamp\Samples\srvvar.asp).

Переадресация

Очень легко написать на ASP скрипт, который будет производить некоторые расчеты, и в зависимости от результатов переадресовывать браузер на разные URL (например, подставлять нужный баннер). Делается это так:

Только надо следить, чтобы до выполнения команды redirect ничего не было записано в Response (даже коментарии HTML).

Электронная почта

Одна из часто встречающихся задач – отправить электронную почту с Web-страницы. На первый взгляд, можно просто написать

Но это приводит к тому, что при отправке формы делается попытка на клиентской машине запустить почтовую программу и создать новое сообщение с данными формы. Если это не получается (почтовая программа не настроена, пользователь не отправил почту, и т.д.) — письмо и не будет отправлено. Гораздо надежнее работает серверное решение.

Для этого существуют внешние компоненты, есть и бесплатные. Например, компонента Jmail от Dimac. Все, что для нее нужно – это адрес SMTP-сервера. Вот пример ее использования:

.asp Расширение файла

Тип файла1 Active Server Page

Разработчик Microsoft
Категория Веб-файлы
Формат Text

This file is saved in a binary format, which requires a specific program to read its contents.

Что такое ASP файл?

ASP-файл — это веб-страница, созданная веб-разработчиком, который находится на веб-сервере и может содержать сценарии, написанные на VBScript или JavaScript. Он анализируется на сервере, который генерирует HTML, который отправляется в браузер клиента. Файлы ASP обычно используются сайтами ASP.NET и веб-сайтами, размещенными на серверах Windows с Microsoft IIS.

Файлы ASP похожи на файлы .HTML , но используются несколько иначе. Когда веб-браузер запрашивает HTML-файл, сервер просто отправляет файл. Однако, когда веб-браузер запрашивает файл ASP, сервер отправляет запрос через механизм ASP, который анализирует файл ASP и генерирует простой HTML-код, который отправляется в браузер клиента. Поскольку страницы ASP обрабатываются на сервере, посетители сайта не видят фактического кода ASP, а всего лишь HTML, сгенерированного из сценариев на странице. Страницы ASP обычно используют расширение «.asp», а не «.html.»

Настройка защиты данных ASP.NET Core Configure ASP.NET Core Data Protection

При инициализации системы защиты данных применяются параметры по умолчанию , основанные на рабочей среде. When the Data Protection system is initialized, it applies default settings based on the operational environment. Эти параметры обычно подходят для приложений, выполняющихся на одном компьютере. These settings are generally appropriate for apps running on a single machine. Существуют случаи, когда разработчику может потребоваться изменить параметры по умолчанию. There are cases where a developer may want to change the default settings:

  • Приложение распределено между несколькими компьютерами. The app is spread across multiple machines.
  • По соображениям соответствия. For compliance reasons.

В этих сценариях система защиты данных предоставляет богатый API настройки. For these scenarios, the Data Protection system offers a rich configuration API.

Как и файлы конфигурации, кольцо ключа защиты данных следует защищать с помощью соответствующих разрешений. Similar to configuration files, the data protection key ring should be protected using appropriate permissions. Вы можете выбрать шифрование неактивных ключей, но это не помешает злоумышленникам создавать новые ключи. You can choose to encrypt keys at rest, but this doesn’t prevent attackers from creating new keys. Таким образом, безопасность приложения затронута. Consequently, your app’s security is impacted. Доступ к расположению хранилища, настроенному с помощью защиты данных, должен иметь только само приложение, аналогично тому, как вы защищаете файлы конфигурации. The storage location configured with Data Protection should have its access limited to the app itself, similar to the way you would protect configuration files. Например, если вы решили сохранить ключ на диске, используйте разрешения файловой системы. For example, if you choose to store your key ring on disk, use file system permissions. Убедитесь, что только удостоверение, под которым выполняется веб-приложение, имеет доступ на чтение, запись и создание этого каталога. Ensure only the identity under which your web app runs has read, write, and create access to that directory. При использовании хранилища больших двоичных объектов Azure только веб-приложение должно иметь возможность чтения, записи или создания новых записей в хранилище больших двоичных объектов и т. д. If you use Azure Blob Storage, only the web app should have the ability to read, write, or create new entries in the blob store, etc.

Метод расширения адддатапротектион возвращает идатапротектионбуилдер. The extension method AddDataProtection returns an IDataProtectionBuilder. IDataProtectionBuilder предоставляет методы расширения, которые можно объединить в цепочку для настройки параметров защиты данных. IDataProtectionBuilder exposes extension methods that you can chain together to configure Data Protection options.

протекткэйсвисазурекэйваулт ProtectKeysWithAzureKeyVault

Чтобы сохранить ключи в Azure Key Vault, настройте систему с помощью протекткэйсвисазурекэйваулт в классе Startup : To store keys in Azure Key Vault, configure the system with ProtectKeysWithAzureKeyVault in the Startup class:

Задайте место хранения ключевых звонков (например, персисткэйстоазуреблобстораже). Set the key ring storage location (for example, PersistKeysToAzureBlobStorage). Расположение должно быть задано, поскольку вызов ProtectKeysWithAzureKeyVault реализует иксмленкриптор , который отключает автоматические параметры защиты данных, включая место хранения ключевых звонков. The location must be set because calling ProtectKeysWithAzureKeyVault implements an IXmlEncryptor that disables automatic data protection settings, including the key ring storage location. В предыдущем примере для сохранения ключа используется хранилище BLOB-объектов Azure. The preceding example uses Azure Blob Storage to persist the key ring. Дополнительные сведения см. в разделе поставщики хранилища Key: службы хранилища Azure. For more information, see Key storage providers: Azure Storage. Вы также можете сохранить ключ в локальной системе с помощью персисткэйстофилесистем. You can also persist the key ring locally with PersistKeysToFileSystem.

@No__t-0 — это идентификатор ключа хранилища ключей, используемый для шифрования ключей. The keyIdentifier is the key vault key identifier used for key encryption. Например, ключ, созданный в хранилище ключей с именем dataprotection в contosokeyvault , имеет идентификатор ключа https://contosokeyvault.vault.azure.net/keys/dataprotection/ . For example, a key created in key vault named dataprotection in the contosokeyvault has the key identifier https://contosokeyvault.vault.azure.net/keys/dataprotection/ . Укажите приложение с ключом распаковки и разрешениями на ключ для хранилища ключей. Provide the app with Unwrap Key and Wrap Key permissions to the key vault.

ProtectKeysWithAzureKeyVault перегрузок: ProtectKeysWithAzureKeyVault overloads:

  • Протекткэйсвисазурекэйваулт (идатапротектионбуилдер, KeyVaultClient, String) позволяет использовать KeyVaultClient для обеспечения возможности использования хранилища ключей системой защиты данных. ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, KeyVaultClient, String) permits the use of a KeyVaultClient to enable the data protection system to use the key vault.
  • Протекткэйсвисазурекэйваулт (идатапротектионбуилдер, String, String, X509Certificate2) позволяет использовать ClientId и сертификат X509Certificate , чтобы система защиты данных использовала хранилище ключей. ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, String, String, X509Certificate2) permits the use of a ClientId and X509Certificate to enable the data protection system to use the key vault.
  • Протекткэйсвисазурекэйваулт (идатапротектионбуилдер, строка, строка, строка) позволяет использовать ClientId и ClientSecret , чтобы система защиты данных использовала хранилище ключей. ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, String, String, String) permits the use of a ClientId and ClientSecret to enable the data protection system to use the key vault.

персисткэйстофилесистем PersistKeysToFileSystem

Чтобы хранить ключи в общем UNC-ресурсе, а не в расположении % LocalAppData% по умолчанию, настройте систему с помощью персисткэйстофилесистем: To store keys on a UNC share instead of at the %LOCALAPPDATA% default location, configure the system with PersistKeysToFileSystem:

Если изменить расположение сохраняемости ключей, система больше не шифрует неактивных ключей автоматически, так как не знает, является ли DPAPI подходящим механизмом шифрования. If you change the key persistence location, the system no longer automatically encrypts keys at rest, since it doesn’t know whether DPAPI is an appropriate encryption mechanism.

Протекткэйсвис @ no__t-0 ProtectKeysWith*

Можно настроить систему для защиты неактивных ключей, вызвав любой из API настройки протекткэйсвис @ no__t-1 . You can configure the system to protect keys at rest by calling any of the ProtectKeysWith* configuration APIs. Рассмотрим приведенный ниже пример, в котором ключи хранятся в общем UNC-ресурсе и шифруются с помощью определенного сертификата X. 509: Consider the example below, which stores keys on a UNC share and encrypts those keys at rest with a specific X.509 certificate:

В ASP.NET Core 2,1 или более поздней версии можно предоставить X509Certificate2 протекткэйсвисцертификате, например сертификат, загруженный из файла: In ASP.NET Core 2.1 or later, you can provide an X509Certificate2 to ProtectKeysWithCertificate, such as a certificate loaded from a file:

Дополнительные примеры и обсуждение встроенных механизмов шифрования ключей см. в разделе неактивных ключей шифрования . See Key Encryption At Rest for more examples and discussion on the built-in key encryption mechanisms.

унпротекткэйсвисаницертификате UnprotectKeysWithAnyCertificate

В ASP.NET Core 2,1 или более поздней версии можно поворачивать сертификаты и расшифровывать ключи в неактивном виде, используя массив сертификатов X509Certificate2 с унпротекткэйсвисаницертификате: In ASP.NET Core 2.1 or later, you can rotate certificates and decrypt keys at rest using an array of X509Certificate2 certificates with UnprotectKeysWithAnyCertificate:

сетдефаулткэйлифетиме SetDefaultKeyLifetime

Чтобы настроить систему на использование времени жизни ключа, равного 14 дням, вместо 90 дней по умолчанию, используйте сетдефаулткэйлифетиме: To configure the system to use a key lifetime of 14 days instead of the default 90 days, use SetDefaultKeyLifetime:

SetApplicationName SetApplicationName

По умолчанию система защиты данных изолирует приложения друг от друга на основе их корневых путей к содержимому , даже если они совместно используют один и тот же физический репозиторий ключей. By default, the Data Protection system isolates apps from one another based on their content root paths, even if they’re sharing the same physical key repository. Это предотвращает понимание приложениями защищенных полезных данных друг друга. This prevents the apps from understanding each other’s protected payloads.

Для совместного использования защищенных полезных данных между приложениями: To share protected payloads among apps:

  • Настройте SetApplicationName в каждом приложении с тем же значением. Configure SetApplicationName in each app with the same value.
  • Используйте одну и ту же версию стека API для защиты данных в приложениях. Use the same version of the Data Protection API stack across the apps. Выполните одно из следующих действий в файлах проекта приложений: Perform either of the following in the apps’ project files:
    • Сослаться на ту же версию общей платформы через метапакет Microsoft. AspNetCore. app. Reference the same shared framework version via the Microsoft.AspNetCore.App metapackage.
    • Сослаться на ту же версию пакета защиты данных . Reference the same Data Protection package version.

дисаблеаутоматиккэйженератион DisableAutomaticKeyGeneration

У вас может быть сценарий, в котором приложение не должно автоматически выполнять откат ключей (создание новых ключей) по мере их истечения. You may have a scenario where you don’t want an app to automatically roll keys (create new keys) as they approach expiration. Одним из примеров могут быть приложения, настроенные в связи «первичная/вторичная», в которой только основное приложение отвечает на вопросы управления ключами, а дополнительные приложения просто имеют доступное только для чтения представление круга ключей. One example of this might be apps set up in a primary/secondary relationship, where only the primary app is responsible for key management concerns and secondary apps simply have a read-only view of the key ring. Вторичные приложения можно настроить так, чтобы они обрабатывали ключевое кольцо как доступное только для чтения, настроив систему с DisableAutomaticKeyGeneration: The secondary apps can be configured to treat the key ring as read-only by configuring the system with DisableAutomaticKeyGeneration:

Изоляция отдельных приложений Per-application isolation

Когда система защиты данных предоставляется узлом ASP.NET Core, она автоматически изолирует приложения друг от друга, даже если эти приложения выполняются в той же учетной записи рабочего процесса и используют один и тот же материал основного ключа. When the Data Protection system is provided by an ASP.NET Core host, it automatically isolates apps from one another, even if those apps are running under the same worker process account and are using the same master keying material. Это в некоторой степени аналогично модификатору IsolateApps из элемента System. Web . This is somewhat similar to the IsolateApps modifier from System.Web’s element.

Механизм изоляции работает путем рассмотрения каждого приложения на локальном компьютере в качестве уникального клиента, поэтому IDataProtector с корнем для любого конкретного приложения автоматически включает идентификатор приложения в качестве дискриминатора. The isolation mechanism works by considering each app on the local machine as a unique tenant, thus the IDataProtector rooted for any given app automatically includes the app ID as a discriminator. Уникальный идентификатор приложения — это физический путь приложения: The app’s unique ID is the app’s physical path:

  • Для приложений, размещенных в службах IIS, уникальный идентификатор — это физический путь IIS приложения. For apps hosted in IIS, the unique ID is the IIS physical path of the app. Если приложение развернуто в среде веб-фермы, это значение является стабильным при условии, что среды IIS настроены одинаково на всех компьютерах в веб-ферме. If an app is deployed in a web farm environment, this value is stable assuming that the IIS environments are configured similarly across all machines in the web farm.
  • Для автономных приложений, работающих на сервере Kestrel, уникальный идентификатор — это физический путь к приложению на диске. For self-hosted apps running on the Kestrel server, the unique ID is the physical path to the app on disk.

Уникальный идентификатор предназначен для того, чтобы выдерживать сброс @ no__t-0both отдельного приложения и самого компьютера. The unique identifier is designed to survive resets—both of the individual app and of the machine itself.

Этот механизм изоляции предполагает, что приложения не являются вредоносными. This isolation mechanism assumes that the apps are not malicious. Вредоносное приложение всегда может повлиять на любое другое приложение, выполняемое в той же учетной записи рабочего процесса. A malicious app can always impact any other app running under the same worker process account. В общей среде размещения, в которой приложения взаимно не считаются доверенными, поставщик услуг размещения должен принять меры по обеспечению изоляции на уровне ОС между приложениями, включая разделение базовых хранилищ ключей приложений. In a shared hosting environment where apps are mutually untrusted, the hosting provider should take steps to ensure OS-level isolation between apps, including separating the apps’ underlying key repositories.

Если система защиты данных не предоставляется узлом ASP.NET Core (например, если создать экземпляр с помощью изоляции приложения DataProtectionProvider ) по умолчанию отключена. If the Data Protection system isn’t provided by an ASP.NET Core host (for example, if you instantiate it via the DataProtectionProvider concrete type) app isolation is disabled by default. Если изоляция приложений отключена, все приложения, которые поддерживаются одним и тем же материалом для ключа, могут совместно использовать полезные данные, если они предоставляют соответствующие цели. When app isolation is disabled, all apps backed by the same keying material can share payloads as long as they provide the appropriate purposes. Чтобы обеспечить изоляцию приложений в этой среде, вызовите метод SetApplicationName объекта конфигурации и укажите уникальное имя для каждого приложения. To provide app isolation in this environment, call the SetApplicationName method on the configuration object and provide a unique name for each app.

Изменение алгоритмов с помощью Усекриптографикалгорисмс Changing algorithms with UseCryptographicAlgorithms

Стек защиты данных позволяет изменить алгоритм по умолчанию, используемый созданными новыми ключами. The Data Protection stack allows you to change the default algorithm used by newly-generated keys. Самый простой способ сделать это — вызвать усекриптографикалгорисмс из обратного вызова конфигурации: The simplest way to do this is to call UseCryptographicAlgorithms from the configuration callback:

По умолчанию EncryptionAlgorithm имеет значение AES-256-CBC, а Валидатионалгорисм по умолчанию — HMACSHA256. The default EncryptionAlgorithm is AES-256-CBC, and the default ValidationAlgorithm is HMACSHA256. Политика по умолчанию может быть задана системным администратором с помощью политики на уровне компьютера, но явный вызов UseCryptographicAlgorithms переопределяет политику по умолчанию. The default policy can be set by a system administrator via a machine-wide policy, but an explicit call to UseCryptographicAlgorithms overrides the default policy.

Вызов UseCryptographicAlgorithms позволяет указать нужный алгоритм из предопределенного встроенного списка. Calling UseCryptographicAlgorithms allows you to specify the desired algorithm from a predefined built-in list. Не нужно беспокоиться о реализации алгоритма. You don’t need to worry about the implementation of the algorithm. В приведенном выше сценарии система защиты данных пытается использовать реализацию CNG AES при запуске в Windows. In the scenario above, the Data Protection system attempts to use the CNG implementation of AES if running on Windows. В противном случае он возвращается к управляемому классу System. Security. Cryptography. AES . Otherwise, it falls back to the managed System.Security.Cryptography.Aes class.

Реализацию можно указать вручную с помощью вызова усекустомкриптографикалгорисмс. You can manually specify an implementation via a call to UseCustomCryptographicAlgorithms.

Изменение алгоритмов не влияет на существующие ключи в кольце ключа. Changing algorithms doesn’t affect existing keys in the key ring. Он влияет только на вновь созданные ключи. It only affects newly-generated keys.

Указание пользовательских управляемых алгоритмов Specifying custom managed algorithms

Чтобы указать пользовательские управляемые алгоритмы, создайте экземпляр манажедаусентикатеденкрипторконфигуратион , указывающий на типы реализации: To specify custom managed algorithms, create a ManagedAuthenticatedEncryptorConfiguration instance that points to the implementation types:

Чтобы указать пользовательские управляемые алгоритмы, создайте экземпляр манажедаусентикатеденкриптионсеттингс , указывающий на типы реализации: To specify custom managed algorithms, create a ManagedAuthenticatedEncryptionSettings instance that points to the implementation types:

Как правило, свойства *Type должны указывать на конкретные, допускающие создание экземпляров (с помощью общедоступного конструктора без параметров) SymmetricAlgorithm и KeyedHashAlgorithm, несмотря на то, что системные специальные параметры, например typeof(Aes) для удобным. Generally the *Type properties must point to concrete, instantiable (via a public parameterless ctor) implementations of SymmetricAlgorithm and KeyedHashAlgorithm, though the system special-cases some values like typeof(Aes) for convenience.

SymmetricAlgorithm должен иметь длину ключа ≥ 128 бит и размер блока ≥ 64 бит, и он должен поддерживать шифрование в режиме CBC с заполнением PKCS #7. The SymmetricAlgorithm must have a key length of ≥ 128 bits and a block size of ≥ 64 bits, and it must support CBC-mode encryption with PKCS #7 padding. KeyedHashAlgorithm должен иметь размер дайджеста > = 128 бит и должен поддерживать ключи длиной, равную длине дайджеста хэш-алгоритма. The KeyedHashAlgorithm must have a digest size of >= 128 bits, and it must support keys of length equal to the hash algorithm’s digest length. KeyedHashAlgorithm строго не обязательно должен быть HMAC. The KeyedHashAlgorithm isn’t strictly required to be HMAC.

Указание пользовательских алгоритмов CNG Windows Specifying custom Windows CNG algorithms

Чтобы указать пользовательский алгоритм CNG Windows с помощью шифрования в режиме CBC с проверкой HMAC, создайте экземпляр кнгкбкаусентикатеденкрипторконфигуратион , содержащий алгоритмную информацию: To specify a custom Windows CNG algorithm using CBC-mode encryption with HMAC validation, create a CngCbcAuthenticatedEncryptorConfiguration instance that contains the algorithmic information:

Чтобы указать пользовательский алгоритм CNG Windows с помощью шифрования в режиме CBC с проверкой HMAC, создайте экземпляр кнгкбкаусентикатеденкриптионсеттингс , содержащий алгоритмную информацию: To specify a custom Windows CNG algorithm using CBC-mode encryption with HMAC validation, create a CngCbcAuthenticatedEncryptionSettings instance that contains the algorithmic information:

Алгоритм блочного блочного шифра должен иметь длину ключа > = 128 бит, размер блока > = 64 бит и должен поддерживать шифрование в режиме CBC с использованием дополнений PKCS #7. The symmetric block cipher algorithm must have a key length of >= 128 bits, a block size of >= 64 bits, and it must support CBC-mode encryption with PKCS #7 padding. Хэш-алгоритм должен иметь размер дайджеста > = 128 бит и должен поддерживать открытие с флагом BCRYPT @ no__t-0ALG @ no__t-1HANDLE @ no__t-2HMAC @ no__t-3FLAG. The hash algorithm must have a digest size of >= 128 bits and must support being opened with the BCRYPT_ALG_HANDLE_HMAC_FLAG flag. Свойства *Provider могут иметь значение null, чтобы использовать поставщик по умолчанию для указанного алгоритма. The *Provider properties can be set to null to use the default provider for the specified algorithm. Дополнительные сведения см. в документации по BCryptOpenAlgorithmProvider . See the BCryptOpenAlgorithmProvider documentation for more information.

Чтобы указать пользовательский алгоритм CNG Windows, используя Галоис/шифрование в режиме счетчика с проверкой, создайте экземпляр кнггкмаусентикатеденкрипторконфигуратион , содержащий алгоритмную информацию: To specify a custom Windows CNG algorithm using Galois/Counter Mode encryption with validation, create a CngGcmAuthenticatedEncryptorConfiguration instance that contains the algorithmic information:

Чтобы указать пользовательский алгоритм CNG Windows, используя Галоис/шифрование в режиме счетчика с проверкой, создайте экземпляр кнггкмаусентикатеденкриптионсеттингс , содержащий алгоритмную информацию: To specify a custom Windows CNG algorithm using Galois/Counter Mode encryption with validation, create a CngGcmAuthenticatedEncryptionSettings instance that contains the algorithmic information:

Алгоритм симметричного блочного шифра должен иметь длину ключа > = 128 бит, размер блока ровно 128 бит и должен поддерживать шифрование GCM. The symmetric block cipher algorithm must have a key length of >= 128 bits, a block size of exactly 128 bits, and it must support GCM encryption. Чтобы использовать поставщик по умолчанию для указанного алгоритма, можно задать для свойства енкриптионалгорисмпровидер значение null. You can set the EncryptionAlgorithmProvider property to null to use the default provider for the specified algorithm. Дополнительные сведения см. в документации по BCryptOpenAlgorithmProvider . See the BCryptOpenAlgorithmProvider documentation for more information.

Указание других пользовательских алгоритмов Specifying other custom algorithms

Несмотря на то, что не предоставляется в качестве API первого класса, система защиты данных достаточно расширяема, чтобы можно было указать практически любой тип алгоритма. Though not exposed as a first-class API, the Data Protection system is extensible enough to allow specifying almost any kind of algorithm. Например, можно хранить все ключи, содержащиеся в аппаратном модуле безопасности (HSM), и обеспечивать пользовательскую реализацию подпрограмм шифрования и расшифровки. For example, it’s possible to keep all keys contained within a Hardware Security Module (HSM) and to provide a custom implementation of the core encryption and decryption routines. Дополнительные сведения см. в статье иаусентикатеденкриптор в разделе расширение криптографии Core . See IAuthenticatedEncryptor in Core cryptography extensibility for more information.

Сохранение ключей при размещении в контейнере DOCKER Persisting keys when hosting in a Docker container

При размещении в контейнере DOCKER ключи должны поддерживаться в одном из следующих: When hosting in a Docker container, keys should be maintained in either:

  • Папка, которая является томом DOCKER, который сохраняется за пределами времени существования контейнера, например общего тома или тома, подключенного к узлу. A folder that’s a Docker volume that persists beyond the container’s lifetime, such as a shared volume or a host-mounted volume.
  • Внешний поставщик, например Azure Key Vault или Redis. An external provider, such as Azure Key Vault or Redis.

Сохранение ключей с помощью Redis Persisting keys with Redis

Для хранения ключей следует использовать только версии Redis, поддерживающие сохраняемость данных Redis . Only Redis versions supporting Redis Data Persistence should be used to store keys. Хранилище BLOB-объектов Azure является постоянным и может использоваться для хранения ключей. Azure Blob storage is persistent and can be used to store keys. Дополнительные сведения см. в разделе проблема GitHub. For more information, see this GitHub issue.

Почему ASP.NET не используют в крупных компаниях?

В настоящий момент С# (asp.net) имеет целый ряд преимуществ над тем, что нам дает Java (в плане удобства и синтаксиса языка). Это правда!

Проблема заключается в том, что Java появился раньше, Java был открытым для использования на Linux. В итоге под сервера на Java написали огромный список уникальных решений, которые сейчас используют топовые команды (посмотри, что такое хадуп, например). В итоге, компании либо не видели смысла переписывать все на C#, так как уже имели билды на Java, либо не хотели тратить время на разработку того, что уже есть на Java.

Именно по этой причине Microsoft сейчас активно начинает спариваться с Linux и везде кричит, что они его любят.

Авторизация в ASP.NET Core MVC

В статье описаны паттерны и приемы авторизации в ASP.NET Core MVC. Подчеркну, что рассматривается только авторизация (проверка прав пользователя) а не аутентификация, поэтому в статье не будет использования ASP.NET Identity, протоколов аутентификации и т.п. Будет много примеров серверного кода, небольшой экскурс вглубь исходников Core MVC, и тестовый проект (ссылка в конце статьи). Приглашаю интересующихся под кат.

Claims

Принципы авторизации и аутентификации в ASP.NET Core MVC не изменились по сравнению с предыдущей версией фреймворка, отличаясь лишь в деталях. Одним из относительно новых понятий является claim-based авторизация, с нее мы и начнем наше путешествие. Что же такое claim? Это пара строк «ключ-значение», в качестве ключа может выступать «FirstName», «EmailAddress» и т.п. Таким образом, claim можно трактовать как свойство пользователя, как строку с данными, или даже как некоторое утверждение вида «у пользователя есть что-то«. Знакомая многим разработчикам одномерная role-based модель органично содержится в многомерной claim-based модели: роль (утверждение вида «у пользователя есть роль X«) представляет собой один из claim и содержится в списке преопределенных System.Security.Claims.ClaimTypes. Не возбраняется создавать и свои claim.

Следующее важное понятие — identity. Это единое утверждение, содержащее набор claim. Так, identity можно трактовать как цельный документ (паспорт, водительские права и др.), в этом случае claim — строка в паспорте (дата рождения, фамилия. ). В Core MVC используется класс System.Security.Claims.ClaimsIdentity.

Еще на уровень выше находится понятие principal, обозначающее самого пользователя. Как в реальной жизни у человека может быть на руках несколько документов одновременно, так и в Core MVC — principal может содержать несколько ассоциированных с пользователем identity. Всем известное свойство HttpContext.User в Core MVC имеет тип System.Security.Claims.ClaimsPrincipal. Естественно, через principal можно получить все claim каждого identity. Набор из более чем одного identity может использоваться для разграничения доступа к различным разделам сайта/сервиса.

На диаграмме указаны лишь некоторые свойства и методы классов из пространства имен System.Security.Claims.

Зачем это все нужно? При claim-based авторизации, мы явно указываем, что пользователю необходимо иметь нужный claim (свойство пользователя) для доступа к ресурсу. В простейшем случае, проверяется сам факт наличия определенного claim, хотя возможны и куда более сложные комбинации (задаваемые при помощи policy, requirements, permissions — мы подробно рассмотрим эти понятия ниже). Пример из реальной жизни: для управления легковым авто, у человека должны быть водительские права (identity) с открытой категорией B (claim).

Подготовительные работы

Здесь и далее на протяжении статьи, мы будем настраивать доступ для различных страниц веб-сайта. Для запуска представленного кода, достаточно создать в Visual Studio 2015 новое приложение типа «ASP.NET Core Web Application», задать шаблон Web Application и тип аутентификации «No Authentication».

При использовании аутентификации «Individual User Accounts» был бы сгенерирован код для хранения и загрузки пользователей в БД посредством ASP.NET Identity, EF Core и localdb. Что является совершенно избыточным в рамках данной статьи, даже несмотря на наличие легковесного EntityFrameworkCore.InMemory решения для тестирования. Более того, нам в принципе не потребуется библиотека аутентификации ASP.NET Identity. Получение principal для авторизации можно самостоятельно эмулировать in-memory, а сериализация principal в cookie возможна стандартными средствами Core MVC. Это всё, что нужно для нашего тестирования.

Для эмуляции хранилища пользователей достаточно открыть Startup.cs и зарегистрировать сервисы-заглушки во встроенном DI-контейнере:

Кстати, мы всего лишь проделали ту же работу, что проделал бы вызов AddEntityFrameworkStores :

Начнем с авторизации пользователя на сайте: на GET /Home/Login нарисуем форму-заглушку, добавим кнопку для отправки пустой формы на сервер. На POST /Home/Login вручную создадим principal, identity и claim (в реальном приложении эти данные были бы получены из БД). Вызов HttpContext.Authentication.SignInAsync сериализует principal и поместит его в зашифрованный cookie, который в свою очередь будет прикреплен к ответу веб-сервера и сохранен на стороне клиента:

Включим cookie-аутентификацию в методе Startup.Configure(app):

Этот код с небольшими модификациями будет основой для всех последующих примеров.

Атрибут Authorize и политики доступа

Атрибут [Authorize] никуда не делся из MVC. По-прежнему, при маркировке controller/action этим атрибутом — доступ внутрь получит только авторизованный пользователь. Вещи становятся интереснее, если дополнительно указать название политики (policy) — некоторого требования к claim пользователя:

Политики создаются в уже известном нам методе Startup.ConfigureServices :

Такая политика устанавливает, что попасть на страницу About сможет только авторизованный пользователь с claim-ом «age», при этом значение claim не учитывается. В следующем разделе, мы перейдем к примерам посложнее (наконец-то!), а сейчас разберемся, как это работает внутри?

[Authorize] — атрибут маркерный, сам по себе логики не содержащий. Нужен он лишь для того, чтобы указать MVC, к каким controller/action следует подключить AuthorizeFilter — один из встроенных фильтров Core MVC. Концепция фильтров та же, что и в предыдущих версиях фреймворка: фильтры выполняются последовательно, и позволяют выполнить код до и после обращения к controller/action. Важное отличие от middleware: фильтры имеют доступ к специфичному для MVC контексту (и выполняются, естественно, после всех middleware). Впрочем, грань между filter и middleware весьма расплывчата, так как вызов middleware возможно встроить в цепочку фильтров при помощи атрибута [MiddlewareFilter].

Вернемся к авторизации и AuthorizeFilter. Самое интересное происходит в его методе OnAuthorizationAsync:

  1. Из списка политик выбирается нужная на основе указанного в атрибуте [Authorize] значения (либо берется AuthorizationPolicy — политика по-умолчанию, содержащая всего одно требование с говорящим названием — DenyAnonymousAuthorizationRequirement.
  2. Выполняется проверка, соответствует ли набор из identity и claim-ов пользователя (например, полученных ранее из cookies запроса) требованиям политики.

Надеюсь, приведенные ссылки на исходный код дали вам представление об внутреннем устройстве фильтров в Core MVC.

Настройки политик доступа

Создание политик доступа через рассмотренный выше fluent-интерфейс не дает той гибкости, которая требуется в реальных приложениях. Конечно, можно явно указать допустимые значения claim через вызов RequireClaim(«x», params values) , можно скомбинировать через логическое И несколько условий, вызвав RequireClaim(«x»).RequireClaim(«y») . Наконец, можно навесить на controller и action разные политики, что, впрочем, приведет к той же комбинации условий через логическое И. Очевидно, что необходим более гибкий механизм создания политик, и он у нас есть: requirements и handlers.

Requirement — не более чем DTO для передачи параметров в соответствующий handler, который в свою очередь имеет доступ к HttpContext.User и волен налагать любые проверки на principal и содержащиеся в нем identity/claim. Более того, handler может получать внешние зависимости через встроенный в Core MVC DI-контейнер:

Регистрируем сам handler в Startup.ConfigureServices(), и он готов к использованию:

Handler-ы возможно сочетать как через AND, так и через OR. Так, при регистрации нескольких наследников AuthorizationHandler , все они будут вызваны. При этом вызов context.Succeed() не является обязательным, а вызов context.Fail() приводит к общему отказу в авторизации вне зависимости от результата других handler. Итого, мы можем комбинировать между собой рассмотренные механизмы доступа следующим образом:

  • Policy: AND
  • Requirement: AND
  • Handler: AND / OR.

Resource-based авторизация

Как уже говорилось ранее, policy-based авторизация выполняется Core MVC в filter pipeline, т.е. ДО вызова защищаемого action. Успех авторизации при этом зависит только от пользователя — либо он обладает нужными claim, либо нет. А что, если необходимо учесть также защищаемый ресурс и его свойства, получить какие данные из внешних источников? Пример из жизни: защищаем action вида GET /Orders/ , считывающий по id строку с заказом из БД. Пусть наличие у пользователя прав на конкретный заказ мы сможем определить только после получения этого заказа из БД. Это автоматически делает непригодными рассмотренные ранее аспектно-ориентированные сценарии на основе фильтров MVC, выполняемых перед тем, как пользовательский код получает управление. К счастью, в Core MVC есть способы провести авторизацию вручную.

Для этого, в контроллере нам потребуется реализация IAuthorizationService . Получим ее, как обычно, через внедрение зависимости в конструктор:

Затем создадим новую политику и handler:

Наконец, проверяем пользователя + ресурс на соответствие нужной политике внутри action (заметьте, атрибут [Authorize] больше не нужен):

У метода IAuthorizationService.AuthorizeAsync есть перегрузка, принимающая список из requirement — вместо названия политики:

Что позволяет еще более гибко настраивать права доступа. Для демонстрации, используем преопределенный OperationAuthorizationRequirement (да, этот пример перекочевал в статью прямо с docs.microsoft.com):

что позволит вытворять следующие вещи:

В методе HandleRequirementAsync(context, requirement, resource) соответствующего handler — нужно лишь проверить права соответственно операции, указанной в requirement.Name и не забыть вызвать context.Fail() если пользователь провалил авторизацию:

Handler будет вызван столько раз, сколько requirement вы передали в AuthorizeAsync и проверит каждый requirement по-отдельности. Для единовременной проверки всех прав на операции за один вызов handler — передавайте список операций внутри requirement, например так:

На этом обзор возможностей resource-based авторизации закончен, и самое время покрыть наши handler-ы тестами:

Авторизация в Razor-разметке

Выполняемая непосредственно в разметке проверка прав пользователя может быть полезна для скрытия элементов UI, к которым пользователь не должен иметь доступ. Конечно же, во view можно передать все необходимые флаги через ViewModel (при прочих равных я за этот вариант), либо обратиться напрямую к principal через HttpContext.User:

Если вам интересно, то view наследуются от RazorPage класса, а прямой доступ к HttpContext из разметки возможен через свойство @Context .

С другой стороны, мы можем использовать подход из предыдущего раздела: получить реализацию IAuthorizationService через DI (да, прямо во view) и проверить пользователя на соответствие требованиям нужной политики:

Не пытайтесь использовать в нашем тестовом проекте вызов SignInManager.IsSignedIn(User) (используется в шаблоне веб-приложения с типом аутентификации Individual User Accounts). В первую очередь потому, что мы не используем библиотеку аутентификации Microsoft.AspNetCore.Identity , к которой этот класс принадлежит. Сам метод внутри не делает ничего, помимо проверки наличия у пользователя identity с зашитым в коде библиотеки именем.

Permission-based авторизация. Свой фильтр авторизации

Декларативное перечисление всех запрашиваемых операций (в первую очередь из числа CRUD) при авторизации пользователя, такое как:

… имеет смысл, если в вашем проекте построена система персональных разрешений (permissions): имеется некий набор из большого числа высокоуровневых операций бизнес-логики, есть пользователи (либо группы пользователей), которым были в ручном режиме выданы права на конкретные операции с конкретным ресурсом. К примеру, у Васи есть права «драить палубу», «спать в кубрике», а Петя может «крутить штурвал». Хорош или плох такой паттерн — тема для отдельной статьи (лично я от него не в восторге). Очевидная проблема данного подхода: список операций легко разрастается до нескольких сотен даже не в самой большой системе.

Ситуация упрощается, если для авторизации нет нужды учитывать конкретный экземпляр защищаемого ресурса, и наша система обладает достаточной гранулярностью, чтобы просто навесить на весь метод атрибут со списком проверяемых операций, вместо сотен вызовов AuthorizeAsync в защищаемом коде. Однако, использование авторизации на основе политик [Authorize(Policy = «foo-policy»)] приведет к комбинаторному взрыву числа политик в приложении. Почему бы не использовать старую добрую role-based авторизацию? В примере кода ниже, пользователю необходимо быть членом всех указанных ролей для получения доступа к FooController:

Подобное решение так же может не дать достаточной детализации и гибкости для системы с большим количеством permissions и их возможных комбинаций. Дополнительные проблемы начинаются, когда нужна и role-based и permission-based авторизация. Да и семантически, роли и операции — разные вещи, хотелось бы обрабатывать их авторизацию отдельно. Решено: пишем свою версию атрибута [Authorize] ! Продемонстрирую конечный результат:

Начнем с создания enum для операций, requirement и handler для проверки пользователя:

Ранее я рассказывал, что атрибут [Authorize] сугубо маркерный и нужен для применения AuthorizeFilter . Не будем бороться с существующей архитектурой, поэтому напишем по аналогии собственный фильтр авторизации. Поскольку список permissions у каждого action свой, то:

  1. Необходимо создавать экземпляр фильтра на каждый вызов;
  2. Невозможно напрямую создать экземпляр через встроенный DI-контейнер.

К счастью, в Core MVC эти проблемы легко разрешимы при помощи атрибута [TypeFilter]:

Мы получили полностью работающее, но безобразно выглядящее решение. Для того, чтобы скрыть детали реализации нашего фильтра от вызывающего кода, нам и пригодится атрибут [AuthorizePermission] :

Обратите внимание: фильтры авторизации работают независимо, что позволяет сочетать их друг с другом. Порядок выполнения нашего фильтра в общей очереди можно скорректировать при помощи свойства AuthorizePermissionAttribute.Order .

Дополнительные материалы для чтения по теме (также приветствуются ваши ссылки для включения в список):

. Часть 1

Интерфейс к базе данных с помощью ASP

Постановка задачи

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

Для начала давайте все-таки разберемся, что же от нас требуется. По сути, необходимо создать базу данных всех статей, подготовить несколько HTML-форм для загрузки статей на сервер, их поиска, сортировки, удаления и, наконец, отображения результата.

Я почти уверен, что подобная задача актуальна применительно практически к любому сайту, тем более что подобным образом (разве что без возможностей поиска, сортировки и удаления) работает большинство гостевых книг (guestbook).

Что нам понадобится

Для реализации вышеизложенной задачи нам потребуется персональный компьютер с Microsoft Windows NT или Windows 2000 (можно и Workstation, и Server), установленный IIS (Internet Information Server), какой-нибудь HTML-редактор (советую использовать Macromedia Dreamweaver), Microsoft Access (версии 95, 97 или 2000) и самый обычный текстовый редактор.

Создание и подготовка базы данных

Прежде всего создадим базу данных статей, для чего:

  • запустим приложение Microsoft Access;
  • любым из известных способов создадим новую базу данных. Назовем ее «Articles»;
  • в созданной базе данных создадим таблицу с именем, например «Articles»;
  • пользуясь инструментом «Конструктор», определим поля нашей таблицы и типы принимаемых ими значений (рис. 1);
  • заполним таблицу несколькими статьями в соответствии с созданными полями (рис. 2);
  • сохраним базу данных в файле «ArticlesDB.mdb».

Далее необходимо прописать нашу базу данных в соответствующем разделе источников данных системы, для этого:

  • запустим программу-конфигуратор источников данных (Data Sources ODBC) — Start->Settings->Control Panel->Administrative Tools->Data Sources ODBC;
  • перейдем во вкладку «System DSN» и создадим новый источник данных, нажав на «Add…»;
  • в появившемся списке драйверов выберем драйвер баз данных Microsoft Access — «Microsoft Access Driver (*.mdb)» и нажмем на «Finish»;
  • в строке «Data Source Name» зададим имя нашей базы данных, например «Articles» (это то имя, по которому мы в дальнейшем будем обращаться к ней);
  • нажмем на «Select…», выберем подготовленный нами файл «ArticlesDB.mdb» и нажмем «OK».

В результате в списке источников данных в вашей системе появится строка, представленная на рис. 3.

Оформляем главную страницу (index.asp)

С ASP работать очень просто. Для этого надо всего лишь вставить текст скрипта ASP в пару тэгов . В остальном ASP-файл ничем не отличается от HTML-файла (за исключением, пожалуй, расширения). Комментарии в HTML, как известно, вставляются в пару тэгов , в ASP же закомментировать строку можно при помощи символа ‘ (апостроф) в ее начале.

Теперь давайте разберемся. Во-первых, как вы наверняка заметили, ASP-код легко сочетается с HTML-тэгами; в этом его достоинство. Так, к примеру, строка Response.Write Link & «
» отображает на экране браузера клиента подготовленное сервером значение переменной Link и HTML-тэг
, то есть перевод строки. Особый интерес вызывает переменная rs. Для искушенных программистов сразу скажу — это указатель. Однако в ASP с целью облегчения работы начинающих указатели маскируются. Здесь не встретишь громоздких С’шных конструкций, типа «я знаю, что ты знаешь, что я знаю», или, выражаясь программистским языком, указатель на указатель… Однако сделано это так искусно, что гибкость программирования при этом не теряется, нет лишь прямой работы с указателями, а только работа с помощью специальных функций, скрывающих от программиста рутину и защищающих указатели от некорректных действий. Таким образом, выражение rs.Fields («Article»).value означает значение поля «Article» текущего значения указателя на элемент базы данных (в нашем случае статей) и содержит текст статьи, которая соответствует текущей позиции указателя на все статьи. Переход к следующему элементу базы (смещение указателя) выполняется с помощью инструкции Rs.MoveNext. В приведенном выше примере это не делается, а попросту формируется ссылка на текст статьи в виде ее названия и отображается комментарий самой первой статьи, соответствующей результату запроса. Давайте попробуем отобразить все статьи нашей базы данных на главной странице в виде HTML. И еще, обратите особое внимание на директиву:

Она по сути формирует ссылку на файл, содержащий шаблон отображения самой статьи, причем передает идентификатор статьи ему в качестве параметра. Полностью файл шаблона приведен в приложении к настоящей статье, а механизм его работы может быть кратко представлен следующим образом:

Первая строчка скрипта шаблона HTML присваивает переменной TheID значение, переданное ссылкой с использованием метода Request.QueryString. Далее открывается база данных, из которой читается статья (запись), соответствующая идентификатору, переданному из главного скрипта (index.asp).

Создаем главную страницу

Таким образом в таблицу в цикле будут добавляться ряды со ссылками на статьи и с аннотациями, пока не будут отображены все статьи из базы данных. Следует обратить внимание на переменную Cnt. По окончании цикла она будет содержать число обработанных статей (рядов таблицы).

Язык структурированных запросов — SQL

Настала пора разобраться с тем, что таится за строчками:

По сути, именно за этими двумя строчками кроется работа с нашей базой данных: первая представляет собой текстовую строку с запросом к базе данных (текстовые строки в ASP записываются в двойных кавычках); вторая — содержит директиву выполнения этого запроса с одновременным присвоением результата переменной (указателю на записи в базе данных). В рамках настоящей статьи мы не будем рассматривать SQL (Structured Query Language) во всех деталях, а остановимся лишь на тех его операторах, без понимания которых дальнейшая работа будет невозможна. Для тех, кому этого покажется недостаточным, советую посетить отобранные мною сайты с детальной документацией по SQL.

Для полноценной работы нам необходимо познакомиться с четырьмя операторами этого мощного языка, предназначенного специально для работы с базами данных.

DELETE удаляет те ряды из «Имя Таблицы», которые удовлетворяют условию, определенному в «Определении», и возвращает число удаленных рядов. Если выполнить команду DELETE без условия WHERE, то все ряды указанной таблицы будут удалены. В этом случае DELETE возвратит 0. Ключевое слово LOW_PRIORITY откладывает выполнение операции DELETE до завершения работы чтения из таблицы других клиентов.

SELECT используется для извлечения рядов (записей) из одной или более таблиц. Выражение_Select определяет столбцы таблицы, значения которых необходимо извлечь. Все ключевые поля должны быть заданы в строгой последовательности. К примеру, выражение HAVING должно следовать за любым выражением GROUP BY и до любого выражения ORDER BY.

Выражение_Select можно заменить псевдонимом (alias) с помощью ключевого слова AS. Псевдоним используется в качестве идентификатора имени столбца и может быть использован наряду с ключевыми словами ORDER BY или HAVING.

Выражение HAVING может относиться к любому столбцу или псевдониму в Выражении_Select. Оно применяется к запросу в последнюю очередь, непосредственно перед посылкой данных клиенту. SELECT . INTO OUTFILE ‘имя_файла’ заносит отобранные записи в файл. Файл создается непосредственно на сервере и не может «уже существовать» (одна из основных причин такого механизма заключается в предотвращении случайного «затирания» различных важных файлов).

INSERT используется для добавления новых записей в существующую таблицу. Допустимо две формы использования INSERT.

Первая форма — INSERT . VALUES — вставляет ряды на основании заданных значений. Вторая форма — INSERT . SELECT — вставляет ряды, выбранные из другой таблицы.

Ключевое слово LOW_PRIORITY откладывает выполнение операции до завершения работы чтения из таблицы других клиентов. Ключевое слово IGNORE в команде INSERT позволяет избегать вставки повторяющихся строк (используется в сочетании с ключевыми словами PRIMARY или UNIQUE). Для второй формы INSERT INTO . SELECT операция не может содержать выражения ORDER BY. Таблица, в которую производится добавление записей, не может присутствовать в выражении FROM части SELECT запроса потому, что запрещено производить выделение из той же самой таблицы, в которую производится вставка.

REPLACE служит для редактирования содержимого таблицы и работает в точности как INSERT, за исключением того, что если старая запись в таблице имеет то же значение, что и записываемая, то старая запись удаляется прежде, чем добавляется новая.

UPDATE обновляет поля существующей таблицы новыми значениями. Выражение SET показывает, какие поля (столбцы) должны быть изменены, и значения, которые должны быть им присвоены. Выражение WHERE, если оно есть, указывает, какие ряды должны быть обновлены. В противном случае операция применяется ко всем рядам таблицы. Ключевое слово LOW_PRIORITY откладывает выполнение операции до завершения работы чтения из таблицы других клиентов. Выражения UPDATE выполняются слева направо.

Обновляет значение поля Password в таблице WAPassword, записывая в поле, чей идентификатор ID равен 1 значение ‘passw’.

Увеличивает значение поля counter таблицы Счетчик на 1.

Удваивает поле age, а затем прибавляет 1 к его значению в таблице persondata.

Что такое Global.asa

Global.asa позволяет выполнять определенные скрипты в начале работы клиентской сессии или при инициализации IIS. Примером тому может служить простейший счетчик числа посещений сайта. Более того, допустимо использовать множественные файлы Global.asa. Однако следует помнить, что ASP-скрипт ищет самый близкий (расположенный в том же каталоге) файл Global.asa и использует именно его.

По сути, этот файл может содержать четыре скрипта: первый будет выполняться при инициализации службы IIS/PWS (Application_OnStart), второй — при остановке службы IIS/PWS (Application_OnEnd) (обычно эти первые два скрипта отрабатывают в процессе перезагрузки компьютера), и еще два скрипта выполняются дополнительно при инициализации сессии пользователя (Session_OnStart) и по ее окончании (Session_OnEnd). Данная схема очень сильно напоминает пары «конструктор-деструктор». Неспроста всякая переменная, которая должна быть использована (например, в текущей сессии), может быть инициализирована в Session_OnStart с тем, чтобы быть использованной в процессе работы сессии, она же уничтожается (обнуляется) в Session_OnEnd.

Global.asa не может содержать тэгов HTML. Недопустимо использование JavaScript. Не рекомендуется писать файл Global.asa с помощью каких-либо HTML-редакторов, для этого гораздо лучше использовать NotePad. И еще один совет: прежде чем вставлять скрипт в файл Global.asa, попробуйте его в работе в обычном ASP-файле.

Пример файла Global.asa

Добавляем новую статью (UploadForm.asp и Upload2DBS.asp)

Теперь, когда мы разобрались с SQL, можно приступать к добавлению новой статьи, причем делать мы это будем прямо с сайта, а если быть точнее — непосредственно с HTML-формы. Для этого сначала создадим файл с самой формой и определим скрипт-реакцию на подтверждение (кнопку «Publish the article!»). (Предполагается, что читатель знаком с азами построения HTML-форм, поэтому мы рассмотрим этот процесс, не вдаваясь в детали построения форм.)

Прежде всего следует уточнить задачу на этом этапе. Итак, очевидно следующее:

  • на загрузку статьи с сайта должен иметь право не каждый (следовательно, желательно предусмотреть пароль для доступа к этой функции);
  • у каждой статьи есть определенная тема (рубрика), причем она не может быть произвольной, а должна выбираться из списка;
  • список можно хранить непосредственно в HTML-файле и, каждый раз изменяя его, изменять сам файл. Это самый простой и быстрый способ;
  • однако для того, чтобы позволить динамически изменять и пополнять этот список, рекомендуется держать его в базе данных. Это позволит пользователям произвольным образом изменять его содержимое и не потребует переделки формы. Для простоты сначала рассмотрим вариант со встроенным («жестко прошитым») рубрикатором.

Как видим, передача управления осуществляется благодаря директиве ACTION=»http://localhost/Upload2DBS.asp»> в тэге формы. Тем самым указывается скрипт-ответ на реакцию пользователя после нажатия на кнопку «Publish the article!». Теперь остановимся на селекторе рубрик. Как уже отмечалось, желательно перевести его содержимое в базу данных. Для этого в нашей базе данных (файл ArticlesDB.mdb) создадим новую таблицу с именем, к примеру «Topics», в которой с помощью конструктора определим всего одно поле — «Topic» типа «текст». Далее заполним эту таблицу произвольными значениями нашего рубрикатора и отсортируем полученный список в алфавитном порядке. После чего следует заменить тэг

Теперь давайте разберемся с самой сутью дальнейшей работы. Что же должен делать наш скрипт-реакция?

Во-первых, следует позаботиться о том, чтобы все обязательные поля (а они отмечены звездочкой) были введены. Наиболее правильным способом проверки этого является скрипт, написанный на любом языке описания скриптов (например, JavaScript), который будет проверять, введены ли значения обязательных полей. Для этого достаточно добавить в определение тэга формы параметр onsubmit=»preprocess();», где preprocess() — имя функции-скрипта, который и будет осуществлять проверку. Здесь как нельзя кстати видно преимущество языков описания сценариев (JavaScript, Jscript, VBScript) перед ASP. ASP выполняется на стороне сервера, а перегружать связь «клиент-сервер» простой проверкой типа «введены ли значения», согласитесь, неправильно. Однако специально в целях обучения мы будем делать это с помощью ASP.

И еще. Прежде чем приступить к выполнению нашей задачи, следует сказать еще об одной небольшой проблеме: когда мы будем вставлять в ячейку базы данных текст, его форматирование (даже самое простое) не сохранится, и в дальнейшем его невозможно будет корректно отобразить на HTML-странице, поскольку поле Memo хранит неформатированную строку текста. Чтобы избежать этого, следует написать функцию, которая позволит производить примитивное HTML-форматирование введенного текста статьи, перед тем как записать его в базу данных. Другими словами, в самом примитивном случае (хотя бы для того, чтобы сохранить исходную разбивку на строки) функция должна вставлять символы конца строки там, где во входном потоке имеются символы переноса строк.

Удаляем статью (RemoveForm.asp и Rem.asp)

Было бы неплохо предусмотреть возможность удаления статьи с нашего сайта: во-первых, она может устареть, а во-вторых, в процессе ее подготовки не исключены ошибки или опечатки. Останавливаться на форме удаления статьи не будем, скажем лишь, что она содержит единственные элементы с запросом пароля и кнопкой удаления (см. файл RemoveForm.asp), и сразу перейдем к рассмотрению непосредственно процесса удаления:

Особое внимание следует уделить первым двум строкам. Они получают значение глобальной переменной текущего сеанса (сессии) работы со значением идентификатора текущей статьи (в нашем случае удаляемой), которая была инициализирована (файл ArtTmp.htm) следующей строкой:

Таким образом, в текущий скрипт передается в качестве параметра сеансовая переменная с идентификатором текущей статьи, которую необходимо удалить. Имеется в виду, что ссылка на удаление присутствует в странице с шаблоном (файл ArtTmp.htm) и удаляемая статья является текущей.

Организуем поиск (SearchForm.asp и SearchDBS.asp)

Как известно, без поиска навигация в сколь-нибудь солидной базе данных невозможна в принципе. Попробуем организовать поиск статьи по ее реквизитам, причем постараемся организовать булев (логический) поиск, соединяя отдельные значения критериев поиска с помощью логики «И/ИЛИ».

Опять же не заостряя внимание на поисковой форме (файл SearchForm.asp), перейдем непосредственно к самому процессу поиска:

Самое интересное происходит при формировании запроса к базе из составляющих:

В зависимости от введенной пользователем комбинации исходных полей из этих компонентов формируется окончательный запрос, в частности для полей «Author» и «Title». Возможны четыре случая: оба поля пусты, пусто первое поле, пусто второе поле и оба поля не пусты. Соответствующая строка SQL-запроса в каждом из этих случаев формируется по-своему. То же самое относится к состоянию селекторов рубрик статей и порядку их сортировки. При добавлении той или иной подстроки учитывается состояние «радиокнопок» И/ИЛИ и соответствующая подстрока добавляется в SQL-запрос, предваряясь логическим элементом «and» или «or» соответственно. После того как окончательный запрос сформирован, он выполняется, а результирующая страница формируется исходя из списка статей, удовлетворяющих критериям.

Полный код приведенных в статье примеров, включая файл базы данных, находится на нашем CD-ROM.

И в заключение

Напоследок хотелось бы сориентировать разработчиков ASP-страниц в мире документации и инструментальных средств. Дело в том, что автор настоящей статьи провел не один день сидя в Интернете в поисках всевозможных исходных текстов, документации, инструментальных средств и теоретических основ этого мощного средства.

Среди множества инструментальных средств, служащих для облегчения создания ASP-приложений, выделяются два: Easy ASP © Eric Banker, 2000 и Microsoft InterDev из комплекта Microsoft Visual Studio 6.0. Первый — очень удобное, несложное и небольшое средство для быстрого создания ASP-приложений. Второй представляет собой мощный, тяжеловесный интегрированный пакет в духе Microsoft для разработки всевозможных Web-приложений.

Временная версия EasyASP 4.0 находится на нашем CD-ROM.

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

http://www.15seconds.com/issue/000210.htm — создание динамичных JavaScript-скриптов с помощью ASP и интерфейсов к базам данных

http://www.alphasierrapapa.com/iisdev/ — сайт, посвященный разработке серверов IIS с помощью ASP

http://www.websiteresources.com/ — огромная база исходных текстов всевозможных Web-программ

Примеры ASP-кода для профессионалов

http://www.asptoday.com/search.asp?category=ASP Tricks — масса полезных советов для начинающих программировать на ASP

http://www.oreilly.com/catalog/aspnut/ — замечательная книга популярнейшей серии «In a Nutshell» всемирно известного издательства O’REILLY «ASP in a Nutshell A Desktop Quick Reference». На сайте бесплатно размещена одна из глав книги

http://www.chilisoft.net/ — версии ASP для различных платформ можно скачать с этого сайта

http://www.willcam.com/sql/ — введение в структурированный язык запросов SQL

SQL Reference and Example Site — хорошо структурированный материал по SQL

Что такое API? Простое объяснение для начинающих

Этот краткий термин на слуху у всех, кто хоть как-то сталкивался с разработкой. Но далеко не все понимают, что именно он обозначает и зачем нужен. Разработчик Пётр Газаров рассказал об API простыми словами в своём блоге.

Аббревиатура API расшифровывается как «Application Programming Interface» (интерфейс программирования приложений, программный интерфейс приложения). Большинство крупных компаний на определённом этапе разрабатывают API для клиентов или для внутреннего использования. Чтобы понять, как и каким образом API применяется в разработке и бизнесе, сначала нужно разобраться, как устроена «всемирная паутина».

Всемирная паутина и удалённые серверы

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

При введении в адресную строку браузера www.facebook.com на удалённый сервер Facebook отправляется соответствующий запрос. Как только браузер получает ответ, то интерпретирует код и отображает страницу.

Каждый раз, когда пользователь посещает какую-либо страницу в сети, он взаимодействует с API удалённого сервера. API — это составляющая часть сервера, которая получает запросы и отправляет ответы.

API как способ обслуживания клиентов

Многие компании предлагают API как готовый продукт. Например, Weather Underground продаёт доступ к своему API для получения метеорологических данных.

Сценарий использования: на сайте небольшой компании есть форма для записи клиентов на приём. Компания хочет встроить в него Google Календарь, чтобы дать клиентам возможность автоматически создавать событие и вносить детали о предстоящей встрече.

Применение API: цель — сервер сайта должен напрямую обращаться к серверу Google с запросом на создание события с указанными деталями, получать ответ Google, обрабатывать его, и передавать соответствующую информацию в браузер, например, сообщение с запросом на подтверждение пользователю.

В качестве альтернативы браузер может сделать запрос к API сервера Google, минуя сервер компании.

Чем API Google Календаря отличается от API любого другого удалённого сервера в сети?

Технически, разница в формате запроса и ответа. Чтобы сгенерировать полную веб-страницу, браузер ожидает ответ на языке разметки HTML, в то время как API Google Календаря вернёт просто данные в формате вроде JSON.

Если запрос к API делает сервер веб-сайта компании, то он и является клиентом (так же, как клиентом выступает браузер, когда пользователь открывает веб-сайт).

Пользователь благодаря API получает возможность совершить действие, не покидая сайт компании.

Большинство современных сайтов используют по крайней мере несколько сторонних API. Многие задачи уже имеют готовые решения, предлагаемые сторонними разработчиками, будь то библиотека или услуга. Зачастую проще и надёжнее прибегнуть именно к уже готовому решению.

Многие разработчики разносят приложение на несколько серверов, которые взаимодействуют между собой при помощи API. Серверы, которые выполняют вспомогательную функцию по отношению к главному серверу приложения, называются микросервисами.

Таким образом, когда компания предлагает своим пользователям API, это просто означает, что она создала ряд специальных URL, которые в качестве ответа возвращают только данные.

Такие запросы часто можно отправлять через браузер. Так как передача данных по протоколу HTTP происходит в текстовом виде, браузер всегда сможет отобразить ответ. Например, через браузер можно напрямую обратиться к API GitHub (https://api.github.com/users/petrgazarov), причём без маркера доступа, и получить вот такой ответ в формате JSON:

Браузер отлично отображает JSON-ответ, который вполне можно вставлять в код. Из такого текста достаточно просто извлечь данные, чтобы использовать их по своему усмотрению.

Ещё несколько примеров API

Слово «application» (прикладной, приложение) может применяться в разных значениях. В контексте API оно подразумевает:

  • фрагмент программного обеспечения с определённой функцией,
  • сервер целиком, приложение целиком или же просто отдельную часть приложения.

Любой фрагмент ПО, который можно чётко выделить из окружения, может заменять букву «А» в англоязычной аббревиатуре, и тоже может иметь некоторого рода API. Например, при внедрении в код разработчиком сторонней библиотеки, она становится частью всего приложения. Будучи самостоятельным фрагментом ПО, библиотека будет иметь некий API, который позволит ей взаимодействовать с остальным кодом приложения.

В объектно-ориентированном проектировании код представлен в виде совокупности объектов. В приложении таких объектов, взаимодействующих между собой, могут быть сотни. У каждого из них есть свой API — набор публичных свойств и методов для взаимодействия с другими объектами в приложении. Объекты могут также иметь частную, внутреннюю логику, которая скрыта от окружения и не является API.

Илон Маск рекомендует:  Алгоритм дейкстра
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL