Общий интерфейс шлюза - Common Gateway Interface - Wikipedia
В вычисление, Общий интерфейс шлюза (CGI) - это спецификация интерфейса для веб-серверы выполнять такие программы, как консольные приложения (также называемый программы интерфейса командной строки ) работает на сервер который динамически генерирует веб-страницы. Такие программы известны как CGI скрипты или просто как CGI. Специфика выполнения сценария на сервере определяется сервером. В общем случае сценарий CGI выполняется во время запроса и генерирует HTML.[1]
Короче говоря, HTTP-запрос GET или POST от клиента может отправлять данные HTML-формы в программу CGI через стандартный ввод. Другие данные, такие как пути URL и данные заголовка HTTP, представлены как переменные среды процесса.
История
В 1993 г. Национальный центр суперкомпьютерных приложений (NCSA) команда написала спецификацию для вызова исполняемых файлов командной строки в списке рассылки www-talk.[2][3][4] Другие разработчики веб-серверов приняли его, и с тех пор он стал стандартом для веб-серверов. Рабочая группа под председательством Кен Коар началась в ноябре 1997 г., чтобы получить более формальное определение CGI в NCSA.[5] Результатом этой работы стало RFC 3875, в котором указан CGI версии 1.1. В RFC конкретно упомянуты следующие участники:[1]
- Роб МакКул (автор NCSA HTTPd Веб сервер )
- Джон Фрэнкс (автор веб-сервера GN)
- Ари Луотонен (разработчик ЦЕРН httpd Веб сервер)
- Тони Сандерс (автор веб-сервера Plexus)
- Джордж Филлипс (специалист по обслуживанию веб-серверов в Университет Британской Колумбии )
Исторически скрипты CGI часто писались на языке C. RFC 3875 «Общий интерфейс шлюза (CGI)» частично определяет CGI с использованием C,[1] говоря, что переменные среды «доступны для подпрограммы библиотеки C getenv () или переменной окружения».
Название CGI пришло из первых дней Интернета, когда вебмастерам хотели подключить устаревшие информационные системы, такие как базы данных, к своим веб-серверам. Программа CGI выполнялась сервером, который обеспечивал общий «шлюз» между веб-сервером и унаследованной информационной системой.
Назначение спецификации CGI
Каждый веб сервер бежит HTTP серверное программное обеспечение, которое отвечает на запросы от веб-браузеры. Обычно HTTP-сервер имеет каталог (папка), который обозначен как коллекция документов - файлы, которые можно отправлять в веб-браузеры, подключенные к этому серверу.[6] Например, если у веб-сервера есть доменное имя example.com
, а его коллекция документов хранится в / USR / местные / apache / htdocs
в локальной файловой системе, тогда веб-сервер ответит на запрос http://example.com/index.html
отправив в браузер (предварительно записанный) файл /usr/local/apache/htdocs/index.html
.
Для страниц, создаваемых «на лету», серверное программное обеспечение может откладывать запросы к отдельным программам и передавать результаты запрашивающему клиенту (обычно веб-браузеру, который отображает страницу конечному пользователю). В первые дни Интернета такие программы обычно были небольшими и написаны на языке сценариев; следовательно, они были известны как скрипты.
Такие программы обычно требуют указания дополнительной информации в запросе. Например, если бы Википедия была реализована в виде сценария, сценарию нужно было бы знать одно: вошел ли пользователь в систему и, если вошел в систему, под каким именем. Содержимое вверху страницы Википедии зависит от этой информации.
HTTP предоставляет браузерам способы передавать такую информацию на веб-сервер, например как часть URL-адреса. Серверное программное обеспечение должно каким-то образом передать эту информацию сценарию.
И наоборот, при возврате скрипт должен предоставить всю информацию, требуемую HTTP для ответа на запрос: HTTP-статус запроса, содержимое документа (если доступно), тип документа (например, HTML, PDF или простой текст). и так далее.
Первоначально разное серверное программное обеспечение могло использовать разные способы обмена этой информацией со скриптами. В результате было невозможно написать сценарии, которые работали бы без изменений для другого серверного программного обеспечения, даже если обмениваемая информация была одинаковой. Поэтому было решено указать способ обмена этой информацией: CGI ( Общий интерфейс шлюза, поскольку он определяет общий способ взаимодействия серверного программного обеспечения со сценариями) .Программы, генерирующие веб-страницы, вызываемые серверным программным обеспечением, работающим в соответствии со спецификацией CGI, известны как CGI скрипты.
Эта спецификация была быстро принята и до сих пор поддерживается всем известным серверным программным обеспечением, таким как Apache, IIS, и (с расширением) node.js на базе серверов.
Раннее использование сценариев CGI было для обработки форм. В начале HTML формы HTML обычно имели атрибут «действие» и кнопку, обозначенную как кнопка «отправить». Когда кнопка отправки нажата, URI, указанный в атрибуте «действие», будет отправлен на сервер с данными из формы, отправленными как Строка запроса. Если «действие» указывает сценарий CGI, сценарий CGI будет выполнен, и затем будет создана HTML-страница.
Использование скриптов CGI
Веб-сервер позволяет своему владельцу настраивать, какие URL-адреса должны обрабатываться какими сценариями CGI.
Обычно это делается путем пометки нового каталога в коллекции документов как содержащего сценарии CGI - часто его имя cgi-bin
. Например, / USR / местные / apache / htdocs / cgi-bin
может быть обозначен как каталог CGI на веб-сервере. Когда веб-браузер запрашивает URL-адрес, указывающий на файл в каталоге CGI (например, http://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query=string
), то вместо простой отправки этого файла (/usr/local/apache/htdocs/cgi-bin/printenv.pl
) в веб-браузер, HTTP-сервер запускает указанный сценарий и передает выходные данные сценария в веб-браузер. То есть все, что сценарий отправляет стандартный вывод передается веб-клиенту вместо того, чтобы отображаться на экране в окне терминала.
Как отмечалось выше, спецификация CGI определяет, как дополнительная информация, передаваемая с запросом, передается в сценарий. Например, если косая черта и дополнительные имена каталогов добавляются к URL-адресу сразу после имени сценария (в этом примере , / с / дополнительным / путем
), то этот путь сохраняется в PATH_INFO
переменная окружения перед вызовом скрипта. Если параметры отправляются в сценарий через HTTP GET запрос (вопросительный знак добавляется к URL-адресу, за которым следуют пары param = value; в этом примере ? and = a & query = строка
), то эти параметры сохраняются в СТРОКА ЗАПРОСА
переменная окружения перед вызовом скрипта. Если параметры отправляются в сценарий через HTTP POST запрос, они передаются скрипту стандартный ввод. Затем сценарий может считывать эти переменные среды или данные из стандартного ввода и адаптироваться к запросу веб-браузера.[7]
Пример
Следующее Perl программа показывает все переменные среды, переданные веб-сервером:
#! / usr / bin / env perl= head1 ОПИСАНИЕprintenv - программа CGI, которая просто печатает свое окружение= вырезатьРаспечатать "Content-Type: text / plain n n";за мой $ var ( Сортировать ключи % ENV ) { printf "% s = "% s " n", $ var, $ ENV{$ var};}
Если веб-браузер выдает запрос переменных среды на http://example.com/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with%20percent%20encoding
, 64-битный Windows 7 веб-сервер работает Cygwin возвращает следующую информацию:
COMSPEC = "C: Windows system32 cmd.exe" DOCUMENT_ROOT = "C: / Program Files (x86) / Apache Software Foundation / Apache2.4 / htdocs" GATEWAY_INTERFACE = "CGI / 1.1" HOME = "/ home / SYSTEM «HTTP_ACCEPT =» текст / html, приложение / xhtml + xml, приложение / xml; q = 0,9, * / *; q = 0,8 »HTTP_ACCEPT_CHARSET =» ISO-8859-1, utf-8; q = 0,7, *; q = 0.7 "HTTP_ACCEPT_ENCODING =" gzip, deflate, br "HTTP_ACCEPT_LANGUAGE =" en-us, en; q = 0.5 "HTTP_CONNECTION =" keep-alive "HTTP_HOST =" example.com "HTTP_USER_AGENT =" Mozilla / 5.0 (Windows NT 6.1; WOW64; rv: 67.0) Gecko / 20100101 Firefox / 67.0 "ПУТЬ =" / home / SYSTEM / bin: / bin: / cygdrive / c / program ~ 2 / php: / cygdrive / c / windows / system32: ... " PATHEXT = ". COM; .EXE; .BAT; .CMD; .VBS; .VBE; .JS; .JSE; .WSF; .WSH; .MSC" PATH_INFO = "/ foo / bar" PATH_TRANSLATED = "C: Программные файлы (x86) Apache Software Foundation Apache2.4 htdocs foo bar "QUERY_STRING =" var1 = value1 & var2 = с% 20percent% 20encoding "REMOTE_ADDR =" 127.0.0.1 "REMOTE_PORT =" 63555 "REQUEST_METHOD =" GET " REQUEST_URI = "/ cgi-bin / printenv.pl / foo / bar? Var1 = value1 & var2 = with% 20percent% 20encoding" SCRIPT_FILENAME = "C: / Pro gram Files (x86) / Apache Software Foundation / Apache2.4 / cgi-bin / printenv.pl "SCRIPT_NAME =" / cgi-bin / printenv.pl "SERVER_ADDR =" 127.0.0.1 "SERVER_ADMIN =" (адрес электронной почты администратора сервера) "SERVER_NAME =" 127.0.0.1 "SERVER_PORT =" 80 "SERVER_PROTOCOL =" HTTP / 1.1 "SERVER_SIGNATURE =" "SERVER_SOFTWARE =" Apache / 2.4.39 (Win32) PHP / 7.3.7 "SYSTEMROOT =" C: Windows "TERM = "cygwin" WINDIR = "C: Windows"
Некоторые, но не все, из этих переменных определены стандартом CGI. Некоторые, например PATH_INFO
, СТРОКА ЗАПРОСА
, и те, которые начинаются с HTTP_
, передать информацию из HTTP-запроса.
Из среды видно, что веб-браузер Fire Fox работает на Windows 7 ПК, веб-сервер Apache работает в системе, которая имитирует Unix, а сценарий CGI называется cgi-bin / printenv.pl
.
Затем программа могла бы сгенерировать любой контент, записать его в стандартный вывод, и веб-сервер передаст его браузеру.
Следующие переменные среды перешли в программы CGI:
- Переменные, специфичные для сервера:
SERVER_SOFTWARE
: имя/версия из HTTP сервер.ИМЯ СЕРВЕРА
: имя хоста сервера, может быть десятичная точка Айпи адрес.GATEWAY_INTERFACE
: CGI /версия.
- Запросить конкретные переменные:
SERVER_PROTOCOL
: HTTP /версия.ПОРТ СЕРВЕРА
: Порт TCP (десятичный).REQUEST_METHOD
: название метода HTTP (см. выше).PATH_INFO
: суффикс пути, если он добавлен к URL-адресу после имени программы и косой черты.PATH_TRANSLATED
: соответствующий полный путь как предполагается сервером, еслиPATH_INFO
настоящее.SCRIPT_NAME
: относительный путь к программе, например/cgi-bin/script.cgi
.СТРОКА ЗАПРОСА
: часть URL после ? персонаж. В Строка запроса может состоять из *имя=ценить пары разделены амперсанды (Такие как var1=val1&var2=val2...) при использовании для отправки форма данные, передаваемые с помощью метода GET, как определено в HTML приложение / x-www-form-urlencoded.УДАЛЕННЫЙ УЗЕЛ
: имя хоста клиента, не устанавливается, если сервер не выполнял такой поиск.REMOTE_ADDR
: айпи адрес клиента (десятичная точка).AUTH_TYPE
: тип идентификации, если применимо.REMOTE_USER
используется навернякаAUTH_TYPE
с.REMOTE_IDENT
: видеть идентификатор, только если сервер выполнил такой поиск.ТИП СОДЕРЖИМОГО
: Тип интернет-СМИ входных данных, если используется метод PUT или POST, как указано в заголовке HTTP.CONTENT_LENGTH
: аналогично размер входных данных (десятичный, в октеты ), если предоставляется через HTTP-заголовок.- Переменные, передаваемые пользовательским агентом (
HTTP_ACCEPT
,HTTP_ACCEPT_LANGUAGE
,HTTP_USER_AGENT
,HTTP_COOKIE
и, возможно, другие) содержат значения соответствующих Заголовки HTTP и поэтому имеют тот же смысл.
Программа возвращает результат на веб-сервер в виде стандартного вывода, начиная с заголовка и пустая строка.
Заголовок кодируется так же, как и Заголовок HTTP и должен включать Тип MIME возвращенного документа.[8] Заголовки, дополненные веб-сервером, обычно пересылаются вместе с ответом обратно пользователю.
Вот простая программа CGI, написанная на Python 3 вместе с HTML, которая решает простую задачу сложения.[9]
add.html
:
<!DOCTYPE html><html> <тело> <форма действие="add.cgi" метод="ПОЧТОВЫЙ"> <набор полей> <легенда>Введите два числа для сложения</легенда> <метка>Первый номер: <Вход тип="номер" имя="num1"></метка><br> <метка>Второй номер: <Вход тип="номер" имя="число2"></метка><br> </набор полей> <кнопка>Добавлять</кнопка> </форма> </тело></html>
add.cgi
:
#! / usr / bin / env python3импорт cgi, cgitbcgitb.включить()входные данные = cgi.FieldStorage()Распечатать('Content-Type: text / html') # HTML следует заРаспечатать('') # Оставляем пустую строкуРаспечатать(' Результаты сложения
')пытаться: число1 = int(входные данные["num1"].ценить) число2 = int(входные данные["число2"].ценить)Кроме: Распечатать('') поднимать SystemExit(1)Распечатать('<выход>{0} + {1} = {2} '.формат(число1, число2, число1 + число2))
Эта программа Python 3 CGI получает входные данные из HTML и складывает два числа.
Развертывание
Веб-сервер, поддерживающий CGI, можно настроить для интерпретации URL что он служит ссылкой на сценарий CGI. Обычное соглашение - иметь cgi-bin /
каталог в основе дерева каталогов и обрабатывать все исполняемые файлы в этом каталоге (и никаком другом в целях безопасности) как сценарии CGI. Еще одно популярное соглашение - использовать расширения файлов; например, если сценариям CGI последовательно предоставляется расширение .cgi
веб-сервер можно настроить для интерпретации всех таких файлов как сценариев CGI. Хотя он удобен и требуется для многих заранее подготовленных сценариев, он открывает сервер для атаки, если удаленный пользователь может загрузить исполняемый код с соответствующим расширением.
В случае HTTP PUT или POST, данные, отправленные пользователем, передаются программе через стандартный ввод. Веб-сервер создает подмножество переменные среды передается ему и добавляет подробности, относящиеся к среде HTTP.
Использует
CGI часто используется для обработки входной информации от пользователя и получения соответствующего вывода. Примером программы CGI является реализация вики. Пользовательский агент запрашивает имя записи; веб-сервер выполняет CGI; программа CGI извлекает источник страницы этой записи (если она существует), преобразует ее в HTML, и распечатает результат. Веб-сервер получает входные данные от CGI и передает их пользовательскому агенту. Если щелкнуть ссылку «Изменить эту страницу», CGI заполнит HTML textarea
или другой элемент управления редактированием с содержимым страницы и сохраняет его обратно на сервер, когда пользователь отправляет форму в нем.
Безопасность
Программы CGI по умолчанию запускаются в контексте безопасности веб-сервера. Когда впервые был представлен ряд примеров сценариев, которые были предоставлены вместе с эталонными дистрибутивами веб-серверов NCSA, Apache и CERN, чтобы показать, как сценарии оболочки или программы C могут быть написаны для использования нового CGI. Одним из таких примеров сценария была программа CGI под названием PHF, которая реализовывала простую телефонную книгу.
Как и ряд других сценариев того времени, этот сценарий использовал функцию escape_shell_cmd (). Предполагалось, что функция будет очищать свой аргумент, который поступает из пользовательского ввода, а затем передавать ввод в оболочку Unix для запуска в контексте безопасности веб-сервера. Сценарий неправильно очищал весь ввод и позволял передавать новые строки в оболочку, что эффективно позволяло запускать несколько команд. Результаты этих команд затем отображались на веб-сервере. Если контекст безопасности веб-сервера позволял это, злоумышленники могли выполнять вредоносные команды.
Это был первый широко распространенный пример веб-атаки нового типа, когда не подвергнутые анализу данные от веб-пользователей могли привести к выполнению кода на веб-сервере. Поскольку пример кода был установлен по умолчанию, атаки были широко распространены и привели к появлению ряда рекомендаций по безопасности в начале 1996 года.[10]
Альтернативы
Вызов команды обычно означает вызов вновь созданного процесс на сервере. Запуск процесса может занять гораздо больше времени и памяти, чем фактическая работа по генерации вывода, особенно когда программу все еще нужно интерпретированный или же составлен Если команда вызывается часто, результирующая рабочая нагрузка может быстро перегрузить сервер.
В накладные расходы участие в создании процесса можно уменьшить с помощью таких методов, как FastCGI интерпретатор "prefork" обрабатывает или запускает код приложения полностью на веб-сервере, используя модули расширения, такие как mod_perl или же mod_php. Другой способ уменьшить накладные расходы - использовать предварительно скомпилированные программы CGI, например написав их на таких языках, как C или же C ++, а не интерпретируемые или компилируемые на лету языки, такие как Perl или же PHP или путем реализации программного обеспечения для создания страниц в виде настраиваемого модуля веб-сервера.
Альтернативные подходы включают:
- Такие расширения, как Модули Apache, NSAPI плагины и ISAPI плагины позволяют стороннему программному обеспечению работать на веб-сервере. Веб 2.0 позволяет передавать данные с клиента на сервер без использования HTML-форм и незаметно для пользователя.[11]
- FastCGI снижает накладные расходы, позволяя одному длительно выполняющемуся процессу обрабатывать более одного пользовательского запроса. В отличие от преобразования приложения в надстройку веб-сервера, приложения FastCGI остаются независимыми от веб-сервера.
- Простой общий интерфейс шлюза или SCGI разработан таким образом, чтобы его было проще реализовать, но он снижает задержку в некоторых операциях по сравнению с CGI.
- Также может быть использована замена архитектуры для динамических сайтов. Это подход, принятый Java EE, который запускает код Java в контейнере сервлетов Java для обслуживания динамического содержимого и, возможно, статического содержимого. Этот подход заменяет накладные расходы на создание и уничтожение процессов гораздо более низкими накладными расходами на создание и уничтожение. потоки, а также предоставляет программисту доступ к библиотеке, поставляемой с Платформа Java, стандартная версия на которой основана используемая версия Java EE.
Оптимальная конфигурация любого веб-приложения зависит от конкретных деталей приложения, объема трафика и сложности транзакции; эти компромиссы необходимо проанализировать, чтобы определить наилучшую реализацию для данной задачи и бюджета времени. Веб-фреймворки предлагают альтернативу использованию сценариев CGI для взаимодействия с пользовательскими агентами.
Смотрите также
- CGI.pm
- Интерфейс шлюза DOS (DGI)
- FastCGI
- Интерфейс шлюза веб-сервера Perl
- Стойка (интерфейс веб-сервера)
- Серверная часть включает
- Интерфейс шлюза веб-сервера
Рекомендации
- ^ а б c RFC3875: Общий интерфейс шлюза (CGI) версии 1.1
- ^ МакКул, Роб (14 ноября 1993 г.). «Серверные скрипты». www-talk (Список рассылки). Получено 2019-05-15.
- ^ «Общий интерфейс шлюза». Хуху NCSA HTTPd. NCSA. Архивировано из оригинал 27 января 2010 г.
- ^ «CGI: общий интерфейс шлюза». W3C. Консорциум World Wide Web. Получено 2019-05-15.
- ^ "Страница проекта RFC общего интерфейса шлюза". Архивировано из оригинал 25 августа 2013 г.
- ^ Сопоставление URL-адресов с расположениями файловой системы HTTP-сервер Apache версии 2.2
- ^ Нельсон, Энн Фулчер и Нельсон, Уильям Харрис Морхед. (2001). Создание электронной коммерции с помощью конструкций веб-баз данных. Бостон, Массачусетс: Эддисон Уэсли.
- ^ CGI Primer (Зеркало на citycat.ru)
- ^ "HTML-формы Abacles". www.abacles.com. Архивировано из оригинал 19 апреля 2016 г.. Получено 6 апреля 2016.
- ^ "phf CGI Script не защищает от символов новой строки". Координационный центр CERT Института программной инженерии. Получено 21 ноября 2019.
- ^ Энрико Марино (11 сентября 2018 г.). Управление информацией в распределенной сети (PDF) (кандидат наук). Университет Рома Тре. Получено 11 февраля 2019.
внешняя ссылка
- GNU cgicc, библиотека классов C ++ для написания приложений CGI
- CGI, стандартный модуль Perl для синтаксического анализа запросов CGI и генерации HTML-ответов.
- Программирование CGI 101: Изучите CGI сегодня!, учебник CGI