Author Archives: Pashaster

About Pashaster

Создатель и основной автор данного проекта. Профессиональный разработчик с 4-летним стажем.

Делаем дамп базы MySQL и экспорт данных в консоли

damp-bazy-mysqlПриветствую вас, друзья! :-)

Сегодня я решил продолжить разговор о работе с MySQL в консоли и уделить внимание процедуре экспорта базы данных MySQL.

В статье я расскажу о том, как сделать дамп базы MySQL, а также производить выгрузку данных из MySQL в Excel файл и csv формат.

Мы рассмотрим различные варианты выборки информации из базы данных сайта: создание дампа одной и нескольких БД, экспорте данных из отдельных таблиц и результатов произвольных SELECT запросов.

А также поговорим о том, как сделать вывод данных из MySQL базы в консоли сервера и командной строке MySQL.

В данной статье я не буду рассказывать о том, как экспортировать данные с помощью phpMyAdmin и других визуальных инструментов.

Во-первых, потому что по данной теме уже достаточно материала в сети. Причём качественного материала, который я не горю желанием копипастить.

А, во-вторых, я уже вкратце сам рассматривал процесс вывода информации из MySQL базы в SQL файл в одной из своих статей, где рассказывал об установке WordPress на хостинг.

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

Хочу, чтобы вы поняли меня правильно: я ни в коем случае не хочу вас обидеть, а просто желаю, чтобы вы потратили своё время с максимальной пользой для дела и получили то, что искали.

На этом вступительная часть окончена и мы переходим к обзору консольных команд для создания дампа базы MySQL, которые я решил рассортировать по объёму сохраняемых данных: начиная от экспорта всей БД, заканчивая отдельными таблицами и результатами произвольных запросов.

Создание дампа базы MySQL через консоль

Хочу в самом начале сделать небольшое уточнение.

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

Также, если кто-то не в курсе, бэкап базы данных MySQL — это, по сути, её дамп, сделанный в определённый период времени, который позволяет восстановить структуру и данные базы при необходимости.

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

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

Для создания дампа БД у MySQL есть встроенная утилита под названием mysqldump, которую нужно использовать за пределами командной строки MySQL в консоли сервера или другой оболочке.

Итак, для самого простого и распространённого варианта — экспорта данных конкретной БД в консоли MySQL для переноса её на другой сервер или внутреннего копирования нужно выполнить следующую команду:

mysqldump -u имя_пользователя -p имя_базы_данных > путь_и_имя_файла_дампа

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

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

mysqldump -u имя_пользователя -p --all-databases > путь_и_имя_файла_дампа

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

mysqldump -u имя_пользователя -p --databases имя_базы_данных1, имя_базы_данных2, ... > путь_и_имя_файла_дампа

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

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

О том, как делать бэкапы определённых таблиц MySQL и получать их данные в читаемом виде, речь пойдёт дальше.

Делаем дамп таблицы MySQL и экспорт данных

Для создания дампа определённых таблиц MySQL базы данных нам понадобится всё та же утилита mysqldump, вызываемая со следующими параметрами:

mysqldump -u имя_пользователя -p имя_базы_данных имя_таблицы1, имя_таблицы2, ... > путь_и_имя_файла_дампа

Ещё при вызове mysqldump можно указывать требуемые таблицы в качестве значения параметра —tables, при использовании которого параметр —databases будет игнорироваться:

mysqldump -u имя_пользователя -p --databases имя_базы_данных1, имя_базы_данных2 --tables имя_таблицы1, имя_таблицы2, ... > путь_и_имя_файла_дампа

Приведённый пример выведет на экран следующую ошибку:

mysqldump: Got error: 1049: Unknown database 'имя_базы_данных1,' when selecting the database

Как видите, будет использоваться только самая последняя БД из списка указанных. В принципе, такое поведение вполне логично, т.к. во всех БД указанных таблиц может не оказаться.

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

А что, если нужно получить просто хранимую в них информацию и, желательно, в читаемом виде, чтобы можно было её отправить менеджеру и просмотреть в обычном текстовом или табличном редакторе? У MySQL есть средства и для этого.

Достичь задуманного нам поможет вариант вызова утилиты mysql из консоли с определёнными параметрами:

mysql -u имя_пользователя -p имя_базы_данных -e "SELECT * FROM имя_таблицы"

Данная команда позволит нам выполнить запрос к требуемой БД и вывести результат в консоль, не заходя в командную строку MySQL.

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

mysql -u имя_пользователя -p -e "SELECT * FROM имя_таблицы" > путь_и_имя_файла

Благодаря данным конструкциям мы можем не только получить данные, хранящиеся во всех полях таблицы, но и в конкретных. Для этого достаточно вместо символа wildcards (*) прописать через запятую требуемые.

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

Если же захотите экспортировать данные из MySQL базы в xls или csv формате, чтобы полученный файл корректно отображался в табличных редакторах, то о том, как это сделать будет рассказано немного позже :-)

Создание бэкапов и вывод данных из MySQL базы с помощью запросов

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

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

Для бэкапа нам понадобится всё та же утилита mysqldump, которую нужно будет вызвать в таком виде:

mysqldump -u имя_пользователя -p имя_базы_данных имя_таблицы --where "уточняющий_запрос" > путь_и_имя_файла_дампа

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

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

mysql -u имя_пользователя -p -e "SELECT * FROM имя_таблицы WHERE уточняющий_запрос" > путь_и_имя_файла

Как вы понимаете, помимо различных уточнений, указываемых в запросе с помощью директивы WHERE, можно использовать и прочие SQL конструкции: JOIN, UNION и т.д.

Статистику собрать получится какую угодно :-)

То же самое действие возможно произвести также при работе в командной строке MySQL с помощью следующей команды:

SELECT * FROM таблица_базы_данных WHERE уточняющий_запрос INTO OUTFILE 'путь_и_имя_файла';

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

Если перечисленное — ваш случай, то с полным списком параметров и вариантов вызова данной команды вы можете ознакомиться здесь — https://dev.mysql.com/doc/refman/5.7/en/select-into.html

Далее речь как раз пойдёт о корректном выводе данных MySQL в xls и csv форматы с помощью данной команды. А с musqldump в рамках данной статьи мы прощаемся.

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

mysqldump -u имя_пользователя -h хост_или_IP_сервера_MySQL -p --no-autocommit --opt имя_базы_данных > путь_и_имя_файла_дампа;

Ради эксперимента я использовал данный вариант для того, чтобы сделать дамп базы MySQL размером в 143 Мб. Последующее восстановление заняло 59 секунд времени против 1 минуты и 3 секунд, когда БД восстанавливалась из дампа, сделанного вызовом mysqldump без специальных параметров.

Согласен, что это мелочь. Но это только в случае данного объёма данных. Если использовать данную методику при создании дампа размером более 1Гб, то разница будет более существенной.

Если вы столкнётесь с такой ситуацией, то не забудьте ещё предварительно запаковать дамп базы MySQL в архив. Лучше всего tar.gz. Тогда восстановление займёт ещё меньше времени.

Экспорт данных из MySQL в Excel и csv файлы

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

Как известно, единственным существенным различием между данными форматами является то, что расширение xls и xlsx имеют файлы, создаваемые в программе Microsoft Office Excel, которая работает только под Windows, а csv файлы являются более универсальными и операции с ними возможны во многих редакторах.

Это не значит, что xls нигде, кроме Microsoft Office Excel, не откроется. Тот же OpenOffice подтверждает обратное.

Но для такой возможности данная поддержка должна присутствовать в программном продукте. csv же файлы доступны для чтения даже в обыкновенном текстовом редакторе типа «Блокнот», только такая форма будет не совсем читабельной.

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

Во-первых, это не оптимально, т.к. такой файл вряд ли откроется при больших объёмах хранящейся в БД информации. А, во-вторых, непонятно, как разбивать внутри файла информацию по таблицам и полям.

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

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

Итак, если мы говорим о том, как сделать экспорт данных из MySQL в xls и csv, то сделать это можно прямо в консоли сервера через утилиту mysql либо в командной строке MySQL, работой с которой я знакомил вас в предыдущей своей статье.

Начнём по порядку.

Экспортировать данные из MySQL базы данных в csv и xls форматы прямо в консоли сервера можно следующими командами.

На Linux системах:

mysql -u имя_пользователя -d имя_базы_данных -p -e "SELECT * FROM таблица_БД;" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > путь_и_имя_файла.csv

В принципе, при крайней необходимости можете сделать данной командой и экспорт данных MySQL в Excel файл. Но я, если честно, на практике данным не занимался и что выйдет в итоге — без понятия, т.к. работаю сейчас под Windows. Если будете пользоваться данной командой под Linux — напишите в комментариях, пожалуйста, о результатах вашей работы. Думаю, информация будет интересна всем.

На Windows:

Экспорт данных из MySQL таблиц в csv приведённой выше командой в данном случае, к сожалению, не удастся, т.к. у Windows, в отличие от Linux, нет встроенной консольной команды для работы с потоками, какой является sed в Linux.

Установить её, конечно, можно, но слишком много хлопот. Ещё, как вариант, можете использовать CygWin — эмулятор консоли Linux для Windows систем.

Хорошо, если она у вас уже установлена. В противном случае экспорт данных из БД MySQL выбранным способом принесёт нам слишком много хлопот.

Зато извлечение информации в xls файл прост как 5 копеек :-) Запустить его очень просто следующим способом, который я опробовал лично:

mysql -u имя_пользователя -d имя_базы_данных -p -e "SELECT * FROM таблица_БД;" > путь_и_имя_файла.xls

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

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

Не знаю, возможно, при произведении каких-либо специфических действий в Microsoft Office Excel и возникнут проблемы в дальнейшем, я так глубоко не копался. При обычном просмотре данных, по крайней мере, я ничего необычного не встретил.

Если у вас в процессе использования экспортированного из MySQL xls файла возникнут какие-то проблемы либо в данной программе, либо в других, то дайте мне знать, пожалуйста, в комментариях.

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

OpenOffice, кстати, всё равно :-) Он автоматически разграничил информацию, полученную способом, которым мы экспортировали содержимое базы MySQL в xls. Не знаю, как он это делает — но рекомендую пользоваться :-)

Ну, а тот же самый Microsoft Office Excel отобразил всю информацию, соответствующую одной записи в таблице, записав её в одну ячейку без каких-либо разделителей. Думаю, что подобным образом поступят и другие редакторы таблиц.

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

И тут я плавно подошёл ко второму способу экспорта MySQL данных в csv и xls, который заключается в использовании командной строки MySQL.

Итак, для того, чтобы экспортировать данные MySQL в csv файл данным способом, нам нужна следующая команда:

SELECT * FROM таблица_базы_данных
INTO OUTFILE 'путь_и_имя_файла.csv'
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n';

В результате её выполнения вы получите csv файл по пути, прописанному вами при вызове, который будет корректно открываться в большинстве современных табличных редакторов. На всякий случай напоминаю, что запускать данную команду нужно только после соединения с базой данных MySQL.

Данная команда также отлично подходит и для экспорта данных MySQL в xls файл для корректного отображения в Microsoft Office Excel. Только в этом случае разделители нам не нужны, т.к. они будут мешать в разбиении информации по ячейкам:

SELECT * FROM таблица_базы_данных INTO OUTFILE 'путь_и_имя_файла.xls';

Однако, на практике не всё так просто, как я описал. Во время выполнения команды вы можете столкнутся со следующей ошибкой в консоли, препятствующей выполнению экспорта:

ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

Она вызвана тем, что ваш MySQL сервер был запущен с опцией —secure-file-priv. Лично я столкнулся с данной проблемой из-за того, что для работы в консоли пользуюсь дистрибутивом MySQL, входящим в комплект WAMP OpenServer, который, в свою очередь запускает MySQL сервер данным образом.

Здесь есть два способа решения проблемы:

  • Изменить параметры запуска MySQL сервера
  • Изменить путь к конечному файлу экспорта MySQL

Первый способ мне показался слишком сложным, т.к. пришлось бы копаться в конфигурации OpenServer, которая не мною была написана со всеми вытекающими из этого обстоятельствами :-) Поэтому я решил пойти вторым путём. Если вы столкнулись с подобной проблемой — повторяйте за мной.

Сперва нужно зайти в командную строку MySQL и выполнить одну из следующих команд:


SHOW VARIABLES LIKE "secure_file_priv";
SELECT @@GLOBAL.secure_file_priv;

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

Т.е. при использовании команд LOAD DATA и SELECT … INTO OUTFILE экспортируемые и импортируемые файлы могут располагаться только внутри данного каталога.

В моём случае у данной переменной было вообще установлено значение NULL, т.к. я, как уже говорил, пользуюсь для работы в консоли утилитами MySQL из дистрибутива, входящего в OpenServer. Данное значение указывало на то, что операции экспорта данных MySQL и импорта с помощью указанных команд были вообще закрыты.

Как потом выяснилось, это распространённая ситуация в случае использования коробочных WAMP и MAMP серверов.

К сожалению, привычными методами изменения значений глобальных переменных MySQL в моём случае воспользоваться не удалось:

SET имя_переменной = значение;

В результате я увидел в консоли лишь следующую ошибку:

ERROR 1238 (HY000) at line 1: Variable 'secure_file_priv' is a read only variable</strong>.

В итоге, чтобы изменить значение переменной secure_file_priv и открыть операции экспорта и импорта, мне потребовалось зайти в файл конфигурации MySQL mysql.ini, который расположен в корневой директории дистрибутива MySQL, или к нему можно получить доступ иным способом, если MySQL входит в комплект вашего WAMP/LAMP/MAMP сборки сервера.

Вам, кстати, если захотите изменить путь к буферному каталогу обмена файлами, нужно будет сделать то же самое.

В моём случае в конфиге данная переменная уже существовала, только в закомментированном виде:

secure-file-priv = "%dprogdir%\\userdata\\temp"

Если у вас её не будет, то пропишите её с нуля в секции [mysqld] (по крайней мере, у меня она располагалась там).

Я её раскомментил и решил использовать в том виде, в каком она была прописана. Т.е. при экспорте данных из MySQL и их импорте обратно файлы у меня теперь будут храниться в каталоге c:\openserver\userdata\temp\.

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

Для уверенности, после перезапуска MySQL сервера ещё раз выводим на экран переменную secure_file_priv и копируем её значение в буфер обмена.

А теперь нам нужно вызвать команду, что и в начале, только перед названием файла, в который будет сохраняться информация из БД MySQL, прописать путь, хранимый в изменяемой нами переменной в следующем виде:

SELECT * FROM таблица_базы_данных INTO OUTFILE 'значение_secure_file_priv\имя_файла.csv';

После этого экспорт данных из MySQL в моём случае заработал.

Важный момент! Если вы работаете с MySQL под Windows, то не забывайте при указании пути к файлу поменять «\» на «/», иначе ошибка с —secure-file-priv всё равно продолжит выводиться.

На этом статья о том, как сделать дамп базы MySQL и её таблиц, а также сделать вывод данных из MySQL таблиц в различные форматы, подходит к концу. Пишите в комментариях свои отзывы и делитесь со всеми своими вариантами скриптов, которыми вы пользуетесь на практике чаще всего.

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

Всем удачи и до новых встреч! :-)

MySQL консоль: 35 основных команд

mysql-komandnaya-strokaДоброго времени суток, коллеги :-)

Да, именно коллеги, потому как простому смертному MySQL командная строка (или MySQL Shell, как её ещё любят называть разработчики), равно как и работа с MySQL в консоли, вряд ли пригодится.

Для того, чтобы данная тема была интересна, нужно быть, как минимум, бэкэнд-разработчиком или начинающим системным администратором, которые не пользуются phpMyAdmin и другими интерфейсами принципиально.

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

Ну что ж… Весьма похвально :-)

В любом случае, я постараюсь, чтобы материал был одинаково интересен и понятен всем, кем бы вы ни работали и как бы вы ни были связаны с программированием. Собственно, чего я своими статьями и добиваюсь, в принципе :-)

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

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

Поехали :-)

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

Сразу скажу, что, если вы не собираетесь работать системным администратором или деплойщиком, то каждый день работать с MySQL через командную строку вам вряд ли понадобиться. Для повседневного использования вполне подойдёт старый добрый phpMyAdmin либо какой-то другой веб интерфейс или приложение для работы с MySQL.

Хотя, здесь имеет место привычка. Лично у меня есть знакомые из ранга «трушных кодеров», которые являются фанатами консоли со времён MS-DOS и чистого Linux, видимо, где работать с ОС можно было только из консоли.

Поэтому они и презирают всякого рода графические «примочки». Хотя, большинству пользователей подойдут именно они.

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

У меня на данный момент их было три:

  1. Впервые я столкнулся с работой в MySQL консоли, когда понадобилось сделать импорт большого дампа БД. Через phpMyAdmin он не загружался целиком, т.к. отваливался где-то посередине по таймауту, несмотря на изменение настроек времени выполнения операции и размеров загружаемых файлов. В принципе, можно было подобрать нужные значения, но мне показалось это слишком длительным процессом.
  2. В следующий раз поработать с MySQL через командную строку пришлось для отключения проверки внешних ключей, когда нужно было удалить данные из таблицы, которая с помощью ключей была связана с другими. В phpMyAdmin я просто не нашёл, как это сделать.
  3. В серьёзных компаниях для работы с MySQL используется исключительно консоль без каких-либо phpMyAdmin-ов. Не знаю почему конкретно, но знающие люди говорили, что это как-то связано с безопасностью. В результате, всем приходилось работать с командной строкой MySQL, в том числе и мне :-)

Но, повторюсь, работа с MySQL в консоли и командной строке вполне подходит и для повседневного использования. Все известные визуальные программы для работы с БД всё равно работают на основе консольных команд MySQL. Поэтому, кому как нравится :-)

Запуск консоли на разных ОС

Поскольку я буду демонстрировать работу с командной строкой MySQL в консоли сервера, то для начала неплохо бы было её запустить.

Действие простое, многим знакомое, для которого достаточно знания «горячих клавиш».

Запуск консоли в Windows:

  • Win+R для открытия командной строки Windows с правами администратора;
  • Вводим команду cmd
  • Нажимаем Enter на клавиатуре

Запуск консоли в Linux дистрибутивах (терминала): в Ubuntu, с которой я работал, достаточно системной комбинации клавиш Ctrl+Alt+T. Про остальные ОС на базе Linux ничего сказать не могу.

Запуска консоли в MacOS: сам я таким не занимался, т.к. Мак-ом ещё не обзавёлся и вряд ли обзаведусь за ненадобностью, но, насколько мне удалось узнать, «горячих клавиш» для вызова терминала в этой ОС нет. Так что если вы являетесь пользователем «яблочной» продукции, то запустите консоль через интерфейс ОС, благо, что мануалов в сети много.

Немного стыдно даже такую информацию публиковать на случай, если на данную статью случайно набредёт какой-то профессиональный системный администратор с бородатым опытом, т.к. он подумает: «Автор считает своих читателей программистами, но при этом учит запускать консоль… Псих какой-то :-)».

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

Основные команды консоли MySQL

Итак, первым делом, нам нужно получить доступ к MySQL командной строке в консоли. Для этого открываем консоль сервера и, если у вас MySQL установлен глобально в виде сервиса, то для «проверки связи» прописываем следующее:


mysql -V

Консольная команда mysql позволяет нам запустить одноименную утилиту, являющуюся командной строкой MySQL.

Это позволит нам узнать версию MySQL, установленного на компьютере и убедиться, что он вообще установлен как служба. Если это так, то в ответ в консоли вы увидите примерно следующий текст: mysql Ver 14.14 Distrib 5.7.16, for Win64 (x86_64).

Да, я не «трушный кодер», потому что сижу под Виндой :-) Но, не суть. На Unix системах процедура будет такой же.

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

В консоли переходим в каталог, где находится исполняемый файл MySQL (на Windows, по крайней мере, это mysql.exe) следующей командой:


cd C:\OpenServer\modules\database\MySQL-5.7-x64\bin

Путь к дистрибутиву у вас, естественно, может отличаться. В качестве примера я решил запустить одну из версий MySQL, входящих в комплект OpenServer.

И запускаем MySQL, проверяя попутно его версию:


mysql.exe -V

В результате в консоль должно было вывестись аналогичное первому случаю сообщение mysql Ver 14.14 Distrib 5.7.16, for Win64 (x86_64).

Всё, с запуском MySQL командной строки через консоль сервера разобрались, теперь будем подключаться непосредственно к серверу MySQL.

Подключение к серверу MySQL в консоли

Cервер MySQL может не обязательно находиться на той же машине, на которой вы пытаетесь получить к нему доступ в консоли. Следовательно, для того, чтобы подключение к удалённому серверу MySQL через консоль было возможно, утилита mysql имеет множество параметров, с помощью которых можно указывать необходимые настройки.

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


mysql

Однако, в таком случае вы получите следующую ошибку: ERROR 1045 (28000): Access denied for user ‘ODBC’@’localhost’ (using password: NO). Так сообщение об ошибке выглядит у меня на Windows. Если же вы используете Linux, то вместо ODBC будет имя вашего системного пользователя, под которым вы совершаете действия в системе.

Всё это потому, что по умолчанию при подключении к MySQL серверу в консоли используется пользователь ODBC на Windows без пароля и системный юзер на Linux с его же паролем. Хост по умолчанию localhost, т.е. данный пользователь может подключаться только с локальной машины.

Поэтому выхода у вас два: либо использовать другого пользователя для входа в командную строку MySQL, либо создать пользователя MySQL с нужной учёткой. Но для второго способа нам без первого всё равно не обойтись :-) Поэтому для начала подключаемся к серверу MySQL под стандартным пользователем root, который создаётся при установке MySQL на компьютер и для которого по умолчанию разрешён доступ с localhost:


mysql -u root -p

При требовании ввести пароль просто нажимаем Enter (если вы его не вводили, конечно, при установке MySQL). После этого вы будете подключены к серверу MySQL с присвоением вам идентификатора подключения и получением доступа к командной строке MySQL.

Если же вы захотите подключиться к серверу MySQL, имеющему специфическое имя хоста или IP или захотите залогиниться под другим пользователем, то используйте команду следующего формата:


mysql -u имя_пользователя -p пароль_пользователя -h хост_или_IP_сервера_MySQL

Вместо кириллических символов с подчёркиванием, естественно, нужно ввести свои данные латинницей. Кстати, данную команду при желании можете прописать немного в другом формате:


mysql --user=имя_пользователя --password=пароль_пользователя --host=хост_или_IP_сервера_MySQL

Если по какой-то причине вы не хотите, чтобы ваш пароль подключения к MySQL отображался в консоли (что правильно, на самом деле), можете использовать следующую команду:


mysql -u имя_пользователя -h хост_или_IP_сервера_MySQL -p

Поскольку пароль не указан явно, вам будет предложено его ввести на следующем шаге. Причём, введённые вами символы отображены не будут даже в виде звёздочек (wildcards), вместо этого будет просто пустая строка.

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

  1. —port или -P — для указания порта подключения к серверу MySQL;
  2. —protocol — протокол, по которому будет осуществляться подключение (возможные варианты: TCP для Windows и Linux, SOCKET для Linux, PIPE и MEMORY для Windows);
  3. —socket или -S — данный параметр пригодится, если вы захотите подключаться через сокеты, следовательно, значение параметра будет сокет;
  4. —pipe или -W — параметр нужен, если вы захотите использовать именованные «трубопроводы» или «пайпы» для подключения;
  5. —shared-memory-base-name — этот параметр вам пригодится для MEMORY подключений через общую память на Windows;

Понятное дело, что на этом список всех параметров подключения к MySQL серверу не ограничивается. В реальности их намного больше.

Если по какой-то причине стандартный вариант с указанием хоста, пользователя и пароля вам не подойдёт, то для выяснения полного перечня параметров подключения вам будет полезна следующая информация — https://dev.mysql.com/doc/refman/5.7/en/connecting.html

Как создать базу данных в MySQL консоли

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

CREATE DATABASE имя_базы_данных;

То же самое действие можно сделать и с помощью специальной MySQL утилиты mysqladmin. Запускается она изолированно от командной строки MySQL, т.е. для её использования вам нужно будет выйти из неё или открыть новую консоль сервера.

А затем вызвать следующую команду:

mysqladmin create имя_базы_данных;

К слову, с помощью утилиты mysqladmin можно не только создавать и удалять базы данных, не заходя в консоль MySQL, но и оперировать серверной конфигурацией, процессами MySQL, управлять репликациями, пинговать сервера и делать ещё много всего интересного.

Более подробно о mysqladmin можете прочитать здесь — https://dev.mysql.com/doc/refman/5.7/en/mysqladmin.html

Как создать пользователя MySQL в командной строке

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

В командной строке MySQL это делается следующим образом:


CREATE USER 'имя_пользователя'@'хост_или_IP_машины' IDENTIFIED BY 'пароль_пользователя';

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

Кстати, при указании хоста для подключения к MySQL серверу можно использовать символ процента — %, который означает, что создаваемый пользователь может соединяться с сервером MySQL с любого IP адреса или хоста.

При этом нужно учитывать, что в данном случае localhost не входит в список адресов, указываемых с помощью %, т.к. localhost обозначает подключение через UNIX сокет вместо стандартного TCP/IP. Т.е. если созданный пользователь MySQL будет подключаться к серверу не с помощью сокетов, а по другому протоколу, указываемому при соединении с MySQL сервером в консоли, то ему нужно будет создавать две учётные записи пользователя:


CREATE USER 'имя_пользователя'@'%' IDENTIFIED BY 'password';
CREATE USER 'имя_пользователя'@'localhost' IDENTIFIED BY 'password';

С созданием пользователя MySQL в консоли мы разобрались. Теперь зададим права пользователя для выполнения любых действий с нашей только что созданной базой данных следующей командой:


GRANT ALL PRIVILEGES ON имя_базы_данных.* TO 'имя_пользователя'@'хост_или_IP_машины';

Опция ALL, как вы поняли, как раз и указывает на то, что пользователю разрешаются любые действия с определённой БД. Полный список прав, которые можно выдавать пользователям с помощью команды GRANT, можно найти здесь (правда, описание параметров на английском) — https://dev.mysql.com/doc/refman/5.7/en/grant.html#grant-privileges

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

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


GRANT ALL ON *.* TO 'имя_пользователя'@'хост_или_IP_машины';

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


FLUSH PRIVILEGES;

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


REVOKE ALL PRIVILEGES ON *.* FROM 'имя_пользователя'@'хост_или_IP_машины';

А затем установите ему нужные с помощью GRANT, как это было описано ранее.

Если же вам в будущем потребуется изменить пароль пользователя MySQL, то для этого достаточно выполнить в MySQL Shell следующие команды:

SET PASSWORD FOR 'имя_пользователя'@'хост_или_IP_машины' = PASSWORD('новый_пароль');

FLUSH PRIVILEGES;

Сброс кэша привилегий MySQL сервера нужен с той же целью, что и при смене прав — без этого действия смена пароля пользователя MySQL может быть не засчитана, поэтому не ленитесь пользоваться :-)

В Интернете, кстати, полно примеров использования следующей команды для сброса пароля MySQL пользователя:

UPDATE mysql.user SET Password=PASSWORD('пароль') WHERE User='имя_пользователя';

Но у меня на MySQL 5.7 данный вариант не сработал, выдав ошибку ERROR 1054 (42S22): Unknown column ‘Password’ in ‘field list’. Её причина оказалось отсутствие поля Password в таблице mysql.user.

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

На этом создание нового пользователя MySQL и обзор действий с его правами и паролями закончен. Идём далее.

Выбор базы данных при работе с MySQL через командную строку

Теперь, после создания пользователя в MySQL Shell и назначения ему прав на работу с БД нам нужно выбрать эту самую базу, чтобы можно было оперировать самой базой и хранящимися в ней данными.

Для этого используем следующую команду в MySQL консоли:


USE имя_базы_данных;

Если всё прошло успешно, то в консоли выведется сообщение Database changed, что будет сигнализировать о том, что мы выполнили вход в базу MySQL через консоль. Кстати, при соединении с сервером MySQL, изначально можно указывать БД, с которой необходимо будет работать. Для этого нужно прописать следующую команду в консоли сервера:


mysql --user=имя_пользователя --password=пароль_пользователя --host=хост_или_IP_сервера_MySQL --database=имя_базы_данных

Или то же самое, только с запросом ввода пароля пользователя MySQL:


mysql -u имя_пользователя -h хост_или_IP_сервера_MySQL имя_базы_данных -p

На этом всё. Думаю, никаких сложностей с подключением к базе данных MySQL через консоль теперь у вас не возникнет :-)

Работа с таблицами MySQL через консоль MySQL

Итак, базу данных MySQL через консоль мы создали. Теперь было бы неплохо научиться с ней работать для случая, когда командная строка MySQL будет единственным средством доступа к хранящимся на сервере данным (как это было у меня, о чём я говорил в начале статьи).

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

CRUD операции, если кто-то не в курсе, — это операции по созданию, чтению, обновлению и удалению данных от англ. «Create, Read, Update, Delete» (возможно, на собеседованиях вам такое понадобится).

Напоминаю, что для выполнения действий с таблицами вы должны сперва подключиться к БД MySQL с помощью команды USE.

Итак, первая на повестке у нас команда создания таблицы MySQL в БД через командную строку, которая выглядит так:


CREATE TABLE имя_таблицы (название_поля_1 тип_поля_1, название_поля_2 тип_поля_2(размер_поля_2), INDEX(название_поля_1), ...);

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

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


CREATE TABLE новое_имя_таблицы LIKE старое_имя_таблицы;
INSERT новое_имя_таблицы SELECT * FROM старое_имя_таблицы;

Данные команды позволяют скопировать структуру таблицы и её данные вместе с индексами и триггерами таблиц. Если вам нужны просто данные и структура (имена полей и их типов данных), то можете обойтись вызовом одной команды:


CREATE TABLE новое_имя_таблицы AS SELECT * FROM старое_имя_таблицы;

Следующая операция из блока CRUD у нас чтение. В случае таблиц чтением будет вывод на экран их структуры. Для этого существует следующие четыре команды:


SHOW FULL COLUMNS FROM имя_таблицы;
DESCRIBE имя_таблицы;
EXPLAIN имя_таблицы;
SHOW CREATE TABLE имя_таблицы;

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

Вторая и третья команды являются просто сокращёнными формами первой команды без расширенной информации. Зачем было их плодить — даже не представляю… Разве что, чтобы было что спросить на собеседованиях при приёме на работу? :-)

Четвёртая команда, помимо имени, типов полей и значений их по умолчанию позволяет получить значения ключей таблиц, движков таблиц (InnoDB, MyISAM), кодировку и др.

Update операция в случае таблиц представляет собой изменение их структуры, т.е. различные действия с полями таблиц MySQL:


ALTER TABLE имя_таблицы DROP COLUMN название_поля;
ALTER TABLE имя_таблицы ADD COLUMN название_поля VARCHAR(20);
ALTER TABLE имя_таблицы CHANGE старое_название_поля новое_название_поля VARCHAR(50);
ALTER TABLE имя_таблицы MODIFY название_поля VARCHAR(3);

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

Тоже самое можно делать и с индексами таблиц с помощью во многом похожих команд:


ALTER TABLE имя_таблицы ADD UNIQUE INDEX имя_индекса (название_поля_1, ...);
ALTER TABLE имя_таблицы rename INDEX старое_имя_индекса TO новое_имя_индекса;
ALTER TABLE имя_таблицы DROP INDEX имя_индекса;

Приведённые команды позволяют добавлять, переименовывать и удалять индексы из таблиц MySQL через командную строку. Для добавления и удаления индексов есть, кстати, ещё альтернативный вариант использования самостоятельных команд, а не делать это через ALTER TABLE. Поэтому при желании можете использовать их:


CREATE UNIQUE INDEX имя_индекса (название_поля_1, ...) ON имя_таблицы;
DROP INDEX имя_индекса ON имя_таблицы;

Приведённые команды являются эквивалентами первой и последней из предыдущего блока. Для переименования индекса, к сожалению, отдельной команды не существует. А для изменения типа индекса, к сожалению, вообще нет никакой возможности в MySQL. Единственный выход — удалить индекс и создать его снова с нужным типом.

Ну, и наконец, мы дошли до последней операции из блока CRUD — к удалению. Удалить таблицы MySQL из БД очень просто. Достаточно в консоли MySQL выполнить следующую команду:


DROP TABLE имя_таблицы;

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

Поэтому, если при удалении или обновлении структуры таблицы или её данных MySQL вернул вам ошибку с текстом Cannot delete or update a parent row: a foreign key constraint fails, то следующая информация вам будет как нельзя кстати.

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

Собственно говоря, с данной целью внешние ключи MySQL и нужны.

Итак, для удаления данных, которому мешают внешние ключи необходимо выполнить следующие действия в консоли MySQL:


SET FOREIGN_KEY_CHECKS=0;
#необходимая_mysql_команда
SET FOREIGN_KEY_CHECKS=1;

Кстати, если захотите удалить внешний ключ, то процедура будет такой же, как и при удалении индекса:


ALTER TABLE имя_таблицы DROP FOREIGN KEY имя_внешнего_ключа;

Чтобы узнать имя внешнего ключа MySQL таблицы, используйте уже знакомую команду MySQL консоли SHOW CREATE TABLE.

Работа с данными таблиц MySQL через командную строку

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

CRUD операции для работы с данными таблиц MySQL будут выглядеть так:

INSERT INTO имя_таблицы (поле1, поле2, ...) VALUES (значение_поля_1, значение_поля_2, ...);
SELECT поле1, поле2, ... FROM имя_таблицы;
UPDATE имя_таблицы SET поле1 = значение_поля_1, поле2 = значение_поля_2;
DELETE FROM имя_таблицы WHERE поле1 = значение_поля_1;

Приведённые выше команды соответствуют операциям создания, чтения, обновления и удаления данных из таблиц БД MySQL. При использовании SELECT и UPDATE также возможно использовать уточняющий оператор WHERE, с помощью которого можно конкретизировать выбор данных способом, описанным в случае использования DELETE.

Также при выборке данных из БД с помощью SELECT можно использовать следующий вариант для получения значений всех полей таблицы:

SELECT * FROM имя_таблицы;

Естественно, что в данных операциях могут использоваться и другие операторы, помимо WHERE. Особенно их много при выборке данных с помощью SELECT: тут и UNION для объединения результатов нескольких запросов, и различные типы JOIN. Все перечислять очень долго и утомительно как для меня, так и для вас будет читать это.

Поэтому давайте договоримся: если вам захочется о чём-то узнать поподробнее — просто напишите об этом в комментариях, и я постараюсь вам ответить. Или же это сделают другие сведущие участники нашего сообщества. Ок? 😉

Так что пока на данном блоке останавливаться не будем.

Если же вам нужно будет удалить все данные из таблицы, то можете воспользоваться следующей MySQL командой:

TRUNCATE имя_таблицы;

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

Как удалить базу данных MySQL через командную строку

Жизненный цикл работы с базой данных подходит к концу и завершается вполне логично — её удалением. Для того, чтобы сделать данную операцию в консоли MySQL, нужно выполнить следующую команду (при этом удаляемая БД может быть и не выбрана командой USE):

DELETE DATABASE имя_базы_данных;

То же самое действие можно сделать и с помощью MySQL утилиты mysqladmin, о которой я уже упоминал в начале статьи при создании БД:

mysqladmin drop имя_базы_данных;

При вызове команды в консоли сервера появится следующее сообщение:

Dropping the database is potentially a very bad thing to do.
Any data stored in the database will be destroyed.

Do you really want to drop the ‘имя_базы_данных’ database [y/N]

Вкратце — это предупреждение о том, что удаление базы данных MySQL — идея очень плохая. Также запрашивается подтверждение действия. Если согласны — пишем y и нажимаем Enter на клавиатуре, после чего на экран выведется следующее сообщение (если всё прошло успешно, конечно же):

Database «имя_базы_данных» dropped

Вот так :-)

Как удалить пользователя MySQL в консоли

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

Начиная с MySQL 5.7 для обоих этих действий существует одна команда:

DROP USER IF EXISTS имя_пользователя;

В более ранних версиях MySQL требовалось две отдельные команды:

GRANT USAGE ON *.* TO 'имя_пользователя'@'хост_или_IP_адрес';
DROP USER 'имя_пользователя'@'хост_или_IP_адрес';

К сожалению, в данном случае сообщение о выполнении операции в консоли MySQL традиционно малоинформативно :-( Поэтому, чтобы узнать, что удаление пользователя пользователь MySQL всё-таки произошло, можно воспользоваться следующей командой, которая выводит на экран список всех существующих на текущем MySQL сервере пользователей:

SELECT User FROM mysql.user;

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

SELECT User, Host, Grant_priv FROM mysql.user;

Также в таблице mysql.user существует масса других полей, в которых хранятся другие типы привилегий и прочая информация, с полным списком которой можно познакомиться здесь — https://mariadb.com/kb/en/library/mysqluser-table/

Не смущайтесь, что это документация к СУБД MariaDB. Технически это то же самое, что и MySQL, т.к. MariaDB является всего лишь её ответвлением или форком от англ «fork» — ответвление, вилка.

Зачем её было делать — снова без понятия :-) Разве что, чтобы всем гордо заявлять, что «у меня своя СУБД»?.. Но о точных мотивах и различиях MySQL и MariaDB я, честно говоря, не сильно в курсе. Поэтому если вы что-то об этом знаете — было бы интересно прочитать об этом в комментариях.

Выход из консоли MySQL

Вот и всё, жизненный цикл БД и пользователя, начавшийся их созданием и завершившийся удалением подошёл к концу. Следовательно, командная строка MySQL, с которой мы работали в консоли сервера с помощью утилиты mysql, нам больше не нужна.

Осталось только выйти из неё…

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

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

vykhod-iz-mysql-v-konsoli

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

Вот и всё, что я хотел вам сегодня рассказать. Надеюсь, что моя шпаргалка по работе с командной строкой MySQL через консоль пригодится не только мне, но и вам.

Говоря о практическом применении изложенной в статье информации хочется напомнить, что приведёнными конструкциями можно пользоваться не только в командной строке MySQL и консоли сервера, но и в консоли phpMyAdmin и прочего ПО, которое предоставляет такую возможность.

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

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

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

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

На этом всё! Удачи и до новых встреч :-)

Что такое SSL, HTTPS и TLS

chto-takoe-httpsВсем доброго времени суток ! :-)

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

В последней, при перечислении различных мер и плагинов для защиты WordPress сайтов от злоумышленников, я вскользь упомянул о протоколе HTTPS и подумал, что кто-то из вас может не знать, что это такое. Да что уж там скрывать: при написании статьи я сам был знаком с данным термином только поверхностно.

Однако, в рамках работы в последнее время всё чаще появляется необходимость установки SSL сертификатов на сайт, да и в саму тему HTTPS протокола я давно хотел углубиться, но всё как-то руки не доходили. В итоге, я решил наконец разобраться в данных вопросах досконально с помощью данного блога, попутно делясь своими знаниями с вами.

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

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

Так что HTTPS даёт не только защищённость данных ресурса, но и является средством SEO оптимизации сайта.

А также мы поговорим о том, зачем нужен SSL сертификат на сайт, который сейчас рекомендую купить и стремятся продать в Интернете на каждом шагу.

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

Поехали!

Что такое HTTPS?

Начнём с истории :-)

Несколько лет назад основным протоколом передачи данных в среде Web был HTTP (Hypertext Transfer Protocol). Алгоритм его работы прост и основан на установке соединения типа «клиент-сервер». При этом обмен информацией производится в текстовом формате, следовательно, возникает риск отслеживания сообщений между клиентами.

В связи с этим в последние годы в Интернете стало популяризироваться использование расширения протокола HTTP под названием HTTPS (HyperText Transfer Protocol Secure).

Браузеры Chrome и Firefox уже отмечают сайты на HTTP как «небезопасные», Google понижает сайты на старом протоколе в выдаче — всё это делается с целью стимуляции вебмастеров перехода с HTTP на HTTPS.

Поэтому возникло даже целое понятие «миграция на HTTPS», поскольку в Рунете и Буржунете ресурсы массово начали осуществлять перевод с HTTP на HTTPS.

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

Кроме вопросов безопасности наличие SSL-сертификата с августа 2014 года положительно влияет на позиции сайта в поисковой выдаче Google, который является главным пропагандистом данного протокола.

Почему же поисковики вдруг взъелись на HTTP и стали заставлять всех переходить на HTTPS?

HTTPS, несмотря на обильное внимание в последнее время, является достаточно древним протоколом, созданным в далёком 1994 году компанией Netscape Communications для своего браузера Netscape Navigator.https-dlya-seo

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

Ещё одним отличием от HTTP является сетевой TCP порт, используемый для передачи данных. Вместо 80 для HTTPS используется 443. Зачем нужен HTTPS для сайта становится понятно после ознакомления со статистикой взломов интернет магазинов, платежных систем и социальных сетей.

Уникальный алгоритм с механизмом самообучения проанализировал взломы 313 190 реальных сайтов, на которых производилось более 760 000 взломов. Больше трети взломов связаны были именно с подменой пакетов при передаче данных.

Что такое TLS и SSL?

Пытаясь разобраться с тем, что такое HTTPS и для чего он нужен, я немного запутался, т.к. при упоминании о данном протоколе постоянно мелькали ссылки на другие протоколы – SSL и TLS.

И то протокол, и то протоколы… Какая между ними связь вообще?

Но, как это часто и бывает, я слишком поспешно изучал новый материал и не заметил маленькую деталь: HTTPS – это протокол передачи данных, а SSL и TLS – это криптографические протоколы. Т.е. это разные типы протоколов и у них, следовательно, разные назначения, что не мешает использовать их все вместе в рамках одного процесса – передачи данных.

Главное отличие HTTP от HTTPS в том, что в последнем данные передаются поверх протоколов SSL и TLS, т.е. сначала шифруются в соответствии с криптографическими протоколами, а потом уже передаются стандартным способом при помощи транспортных протоколов (например, TCP/IP, как и при использовании HTTP).

Если интересно, что такое криптографический протокол, то, согласно Википедии, это – набор криптографических алгоритмов (способов шифрования), который определяет порядок их применения и способы использования.

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

SSL (Secure Sockets Layer — уровень защищённых сокетов) появился достаточно давно, в 1995 году, практически одновременно с изобретением самого HTTPS.

А в 1999 году SSL, находясь в версии 3.0, плавно перешёл в другой криптографический протокол TLS (Transport Layer Security — Протокол защиты транспортного уровня), который активно используется по сей день наряду с SSL.

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

В связи с этим, TLS сейчас имеет версию 1.2, которая была выпущена в 2008 году, а SSL и вовсе прекратил своё развитие, оставшись вечно молодым с 1996 года, когда был выпущен SSL 3.0.

Несмотря на то, что эти протоколы родственные и даже используются вместе, из-за чего в литературе можно встретить их упоминание в связке TLS/SSL, работают они всё-таки по-разному.

В связи с этим разработчикам на практике часто приходится совершать дополнительные действия, чтобы информация, защищаемая с помощью TLS/SSL передавалась и распознавалась корректно.

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

Хорошо, с тем, как взаимодействуют HTTPS, SSL и TLS более-менее разобрались. А что такое SSL сертификат и каким он боком к HTTPS?

Что такое SSL сертификат?

SSL сертификат – это, как раз, и есть один из защитных механизмов, который используется для шифрования данных при передаче их с применением криптографического протокола TLS/SSL. Именно благодаря наличию сертификата безопасности, можно использовать протокол HTTPS, который и был разработан для создания зашифрованных каналов передачи данных.

doverennyj-ssl-sertifikatПо сути, SSL сертификат является уникальным шифром, с помощью которого кодируется информация, что делает возможным её чтение только тем, кому этот ключ известен.

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

Помимо способа шифрования, SSL сертификат содержит также следующую информацию:

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

SSL сертификаты выпускаются центрами сертификации (CA — Certification Authority). Также для передачи данных по протоколу SSL возможно использовать «пустой» сертификат (содержит фиктивную информацию о домене и владельце, нужен лишь в тестовых целях для настройки HTTPS соединения) и самоподписанный, более подробно о котором мы поговорим далее.

Окей, для чего нужен SSL сертификат на сайт — понятно, но как он работает?

Как работает SSL сертификат?

Существует два основных пути шифрования информации: симметричным ключ (общий секретный ключ) и асимметричный (открытый ключ). Протокол SSL/TLS поддерживает оба.

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

Данный тип шифрования использует следующие алгоритмы: DES, 3-DES, RC2, RC4 и AES.

SSL сертификат является частным случаем сертификата открытого ключа, область применения которого не ограничивается только лишь Вебом, на самом деле.

Асимметричный SSL ключ состоит из двух ключей. Один из них является открытым, который, как правило, публикуется в самом сертификате, а другой – секретным, который никому не сообщается.

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

Таким образом, SSL сертификат используется для подтверждения подлинности сервера клиентом и наоборот.

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

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

Это и создаёт защищённый туннель передачи информации, который защищает её от хищения и изменений.

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

Схематично принцип работы HTTPS можно представить следующим образом:

princip-raboty-https

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

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

Когда после прохождения всех проверок подлинности соединение между клиентом и сервером по протоколу HTTPS всё-таки установлено, в браузере напротив URL загорается красивый зелёный значок, свидетельствующий о защищённости соединения. В разных браузерах его вид может отличаться:

kak-vyglyadit-https-v-raznykh-brauzerakh

Самым распространённым алгоритмом асимметричного SSL шифрования является RSA.

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

Ох уж эта безопасность… Вечно в ней всё запутано :-)

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

Виды SSL сертификатов и их группы

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

Каким образом? Всё просто: стоимость SSL сертификатов различается от их предназначения и области применения.

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

Итак, какие же виды SSL сертификатов существуют и когда какой лучше использовать?

Типы SSL сертификатов по типу валидации

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

Считается, что чем больше данных лица, подающего заявку на оформление SSL сертификата (CSR — Certificate Signing Request), проверяется, тем сложнее его будет подделать и тем большую защиту он будет предоставлять.

От этого также зависит стоимость сертификатов и срок их оформления.

Самоподписанный SSL сертификат (SSC — Self Signed Certificate)

Я решил начать с данного типа, т.к. получить его проще всего и он является единственным абсолютно бесплатным SSL сертификатом среди всех существующих. Самозаверенный, самоизданный, самосозданный — как только данный SSL сертификат не называют :-)

Но у всех этих слов корень «сам», который говорит о том, что содержащаяся в самоподписанном SSL сертификате информация проверена самим создателем. Другими словами, создатель сертификата в данном случае является одновременно и центром сертификации (CA).

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

Он делает возможной Main-In-The-Middle атаку на сайт, в ходе которой злоумышленник может перехватить сертификат инициатора зашифрованного соединения и использовать его для дешифровки закодированных данных, передаваемых по HTTPS.

А поскольку данный сертификат не выдан CA, то и отозвать его нельзя, т.е. прервать атаку также не представляется возможным. Разве что закрыть доступ к ресурсу полностью, что крайне нежелательно.

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

samopodpisannyj-ssl-sertifikat-ustanovit

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

Поэтому самоподписанный SSL сертификат для основного сайта не годится. Его можно использовать для тестирования HTTPS настроек сервера и сайта, а также для внутренних целей (например, когда на основном ресурсе соединение производится по HTTPS и поэтому его нужно настроить на DEV и STAGE окружениях).

Если хотите, чтобы SSL сертификат увеличивал ваши позиции в поисковой выдаче и повышал доверие пользователей — закажите другой тип сертификата.

SSL сертификат, подтверждающий доменное имя (Essential, DV — Domain Validation)

На этот вид приходится более 70 % всех сайтов на HTTPS в Рунете, т.к. данные SSL сертификаты самые дешёвые и порядок их оформления практически моментальный. Регистрация SSL сертификатов с проверкой прав на владение доменом доступна как физическим, так и юридическим лицам.

Определить сайты с установленным DV SSL сертификатом легко – в адресной строке браузера возле доменного имени светится закрытый зелёный замок.

doverennyj-ssl-sertifikat-v-brauzere

При выдаче такого сертификата в CA (сертификационный центр) отправляется письмо с запросом, который будет удовлетворён лишь когда выяснится, что у вас есть права на владение доменом.

Для этого email, с которого вы отправляете заявку на получение SSL сертификата, должен быть прописан либо в доменной информации WHOIS либо иметь в качестве почтового домена доменное имя сайта, т.е. быть в формате mail@sitename.zone.

Кстати, последний тип email должен иметь в качестве имени только определённые названия, т.е. если вы захотите заказать SSL сертификат для сайта site.ru, то запрос на его получение вы сможете послать в сертификационный центр лишь со следующих email:

  • admin@site.ru
  • administrator@site.ru
  • hostmaster@site.ru
  • postmaster@mail.ru
  • webmaster@mail.ru

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

Также, в качестве альтернативных оправке email средств подтверждения регистрации SSL сертификата компании-регистраторы могут использовать размещение на сайте текстового пустого файла с хэш-названием либо просьбу изменить DNS запись домена сайта, чтобы вы могли подтвердить свои права на обладание доступа к ней.

При рассмотрении заявки на получение DV сертификата, как уже было сказано, проверяются только права на владение доменом, на остальную информацию внимание не обращается. Равно как никакая другая информация, публикуемая в SSL сертификатах других типов, в самом сертификате не указывается.

Этот тип SSL сертификата подходит для большинства сайтов, которым HTTPS соединение нужно только лишь для удовлетворения критерий Google и повышения позиций в поисковой выдаче.

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

SSL сертификаты, подтверждающие организацию (Instant, OV — Organization Validation)

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

Физическое лицо OV сертификат получить не может, регистрация SSL сертификата данной вида доступна только юридическим лицам.

После получения центром сертификации заявки на регистрацию проверяется существование указанной организации и её права на домен. Процесс этот не быстрый, вследствие чего сертификат будет выпускаться в течении 3-10 дней после подачи заявки.

Говоря по правде, на практике Instant SSL сертификат ничем не отличается от Essential, т.к. в браузере сайты с данными сертификатами отображаются одинаково — в адресной строке возле доменного имени каждого будет присутствовать зелёный закрытый замок.

informaciya-ob-ssl-sertifikata

Но при этом процедура оформления его сложнее и дольше, чем у предыдущего. Также цена SSL сертификата данного вида будет выше, чем у DV.

Всё это лишь для того, чтобы ваша организация была указана в сертификате, который обычные пользователи редко просматривают. Единственная польза этого шага в том, что если вы закажете OV сертификат для своего сайта, а затем злоумышленники получат доступ к вашему email, указанному в WHOIS информации о домене, то они не смогут подделать ваш сертификат, т.к. не смогут подтвердить права на владение организацией, указанной в оригинальном сертификате.

Таким образом, OV SSL сертификат более безопасный, чем DV, и если у вас есть официально зарегистрированная компания, то лучше остановиться всё-таки на данном варианте.

Если вы хотите оформить именно данный тип SSL сертификата, то заранее приведите в порядок информацию (и для ускорения процедуры переведите её на английский язык), которая будет проверяться CA при выдаче данного SSL сертификата:

  1. Наличие компании в «жёлтых страницах», т.е. в телефонных справочниках организаций. Для регистрации в таком справочнике можете воспользоваться сайтом yp.ru.
  2. Указание организации в WHOIS данных домена, что подтверждает права владения доменным именем.
  3. Документы о регистрации компании.
  4. Также будьте готовы к телефонному звонку из CA на номер, указанный в форме заказа SSL сертификата, или на номер, прописанный в WHOIS данных домена. Будьте готовы, что диалог может вестись на английском языке.

Не факт, что все эти данные будут проверяться, но лучше быть подготовленным :-)

SSL сертификаты с расширенной проверкой (EV — Extended Validation)

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

chto-takoe-https-greenline

За эту особенность данный тип SSL сертификатов часто называют «зелёной строкой (Green Line)». Такое новшество увеличивает уровень доверия пользователей к сайту.

Стоит сказать, что порядок выпуска Extended SSL сертификатов не только долгий (порядка 10-14 дней), но ещё и соответствует определённым стандартам, которые были озвучены на специализированном форуме CA/Browser Forum в 2007 году. Он состоит из следующих этапов, выполняемых центром сертификации перед выпуском EV сертификата:

  1. Проверка физической, правовой и операционной деятельности субъекта (компании, получающей сертификат).
  2. Соответствие информации об организации официальным документам.
  3. Проверка организации на обладание исключительными правами на использование домена.
  4. Проверка правомочности выпуска организации Entended Validation SSL-сертификата.

При проверке организации центром сертификации обращают внимание на ту же информацию, что и для OV SSL сертификатов. Следовательно, и сама регистрация доступна только юридическим лицам.

Также следует отметить, что не всякий CA имеет право на выдачу такого сертификата. Для того, чтобы центр сертификации мог выдавать EV SSL сертификаты, он сам должен соответствовать указанным выше требованиям и ежегодно подтверждать это соответствие.

Да, неудобства создаются серьёзные, но зато подделать такой сертификат практически невозможно, за что его часто называют SSL сертификатом повышенной надёжности.

Именно поэтому данный тип SSL сертификатов можно встретить на сайтах различных коммерческих структур (банки, платёжные системы и др., через сайты которых производятся различные финансовые операции и проходят другие секретные данные пользователей).

Стоимость SSL сертификата повышенной надёжности также самая высокая из всех перечисленных ранее.

Виды SSL сертификатов, учитывающих прочие особенности

Основные типы SSL сертификатов по проверяемой при их регистрации информации мы рассмотрели. Но сертификаты различаются не только по указанному признаку.

poluchit-besplatnyj-ssl-sertifikatДа, тип валидации — основное различие, определяющее основные пункты меню выбора сертификата при заказе его у регистраторов через сайты. Однако, если выбрать какой-то конкретный, то можно обнаружить множество опций, оформленных в виде полей для проставления галочки, которые соответствуют дополнительным особенностям SSL сертификатов.

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

SSL сертификаты с поддержкой повышения уровня шифрования (SGC)

Данный вид SSL сертификатов является устаревшим и был актуален только во времена повсеместного использования старых браузеров, поддерживающих только 40 или 56 битное шифрование.

При использовании данного сертификата уровень шифрования принудительно повышался до 128 бит.

Сейчас смысл такие SSL сертификаты приобретать отсутствует. Тем более, что стоят они достаточно недёшево.

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

Групповые SSL сертификаты (WildCard)

Данный вид SSL сертификатов можно использовать не только для основного сайта, но и для его поддоменов.

Мало кто знает, но имя сайта в формате site.ru и www.site.ru — это два разных доменных имени, поэтому если вам нужно, чтобы HTTPS соединение было доступно с сайтом в обоих случаях, то WildCard сертификат — это то, что вам нужно (данная особенность может быть оформлена в виде отдельной опции).

При покупке данного типа SSL сертификата стоит учитывать, что они стоят дороже обычных и смысл их покупать есть только если у вас много поддоменов.

Мультидоменные SSL сертификаты (SAN — Subject Alternative Name, MDC — Multi-Domain Certificate, UCC — Unified Communications Certificate)

Также, как и предыдущий вид SSL сертификата, может использоваться одновременно для нескольких сайтов. Но, в отличие от WildCard, с помощью одного SAN сертификата возможно организовывать HTTPS подключение к ресурсам с различными доменными именами, расположенным на одном сервере.

При этом у ресурсов, использующих единый SAN SSL сертификат, может быть как один, так и разные IP адреса.

Кстати, данный тип SSL сертификата можно использовать в ситуациях, когда вам необходимо настроить HTTPS подключение как к различным ресурсам, так и к их поддоменам.zachem-nuzhen-https-dlya-sajta

Т.е. SAN сертификаты будут идеальным вариантом для вебстудий и фрилансеров, т.к. позволят вам немного сэкономить при массовом подключении HTTPS своим клиентам. только при условии большого числа заказов, естественно, т.к. мультидоменный SSL сертификат — удовольствие не из дешёвых.

Количество доменов, использующих один такой сертификат ограничено и зависит от цены SSL сертификата. «Зелёную строку» данный тип сертификата не позволяет сделать ни на одном из подключаемых доменов.

Однако, есть и ещё одна «ложка дёгтя»: поскольку Green Line данные сертификаты не предоставляют, то подделать их проще, чем стандартные одиночные EV SSL сертификаты. А если взломают один сайт, то автоматически злоумышленники получат доступ ко всем остальным и их поддоменам, использующий общий сертификат.

SSL сертификаты с поддержкой IDN

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

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

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

SSL-cертификаты для ПО (CodeSigning SSL)

Напоследок я решил оставить самый специфичный тип SSL сертификата, который пригодится достаточно ограниченному кругу лиц.

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

CodeSigning SSL сертификат еще называют сертификатом разработчика.

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

Сколько стоит SSL сертификат?

С классами SSL сертификатов мы разобрались. При их перечислении я неоднократно упоминал, что стоимость у них различна от их особенностей.

skolko-stoit-ssl-sertifikatТеперь, когда мы все их изучили, пришло время разобраться со стоимостью SSL сертификатов, т.к. многих от положительного решения вопроса о том, нужен ли SSL сертификат сайту останавливает порой именно эта информация.

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

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

Итак:

  • Самоподписанный SSL сертификат — абсолютно бесплатный, но подходит только для тестовых целей;
  • DV – от 10-20$ в год, бесплатный SSL сертификат можно получить только для некоммерческого использования (например, персональных блогов без монетизации) или лишь на ограниченное время;
  • OV — от 50-60$ до нескольких сотен в год;
  • EV – от 150-300$ в год;
  • Wildcard — от 100 $ в год, т.е. смысл его есть приобретать, если у вас есть более 5 поддоменов;
  • SAN – от 60 $, в зависимости от количества доменов;
  • SGC — от 300$ в год, так что при наличии лишних денег лучше вместо этой опции купить мультидоменный SAN;
  • IDN — за данную опцию, как правило, дополнительно доплачивать не придётся;
  • CodeSigning SSL — от 90$ в год.

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

Где купить SSL сертификат?

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

  1. Comodo
  2. Twawte
  3. Geotrust
  4. GoDaddy
  5. GlobalSign
  6. Symantec

Статистика выпуска SSL сертификатов данными компаниями выглядит так:

zachem-nuzhen-ssl-sertifikat

Если говорить о хостинг-провайдерах, то могу порекомендовать те, услугами которых пользуюсь лично уже на протяжении более 2 лет — TheHost, у которого можно купить дешёвые SSL сертификаты можно, начиная от 7,5$ в год, и AvaHost, которые вообще выдают SSL сертификаты бесплатно своим клиентам. Если не верите — убедитесь сами :-)

Если захотите воспользоваться услугами второго хостера, то у меня для вас приятная новость — это эксклюзивный промокод на скидку в 20% на услуги AvaHost исключительно для читателей и друзей проекта cccp-blog.com. Используйте его при регистрации и экономьте ещё больше — AVA-CCCPBLOG

При покупке SSL сертификатов помимо перечисленных ранее особенностей следует учитывать ещё и следующие:

  • У SSL разная скорость выпуска. Одни станут доступными для вас уже через 10 минут, а другие придется ждать несколько недель.
  • Некоторые сертификаты даются лишь на 1 год, без возможности перевыпуска по старой цене.
  • Центры сертификации предоставляют гарантию пользователям, как дополнительный актив и подтверждение репутации. Например, если ваш сайт взломают через подделку SSL сертификата, вы сможете получить компенсацию от 10000$ до нескольких миллионов.
  • Некоторые регистраторы предоставляют тестовый период, в течении которого пользоваться SSL сертификатом можно бесплатно.
  • Часто у регистраторов встречаются всякого рода акции, в рамках которых SSL сертификат можно получить бесплатно при заказе доменного имени либо с громадными скидками в 50% и выше.
  • Возврат средств (манибэк, moneyback) в течении 30 дней после покупки, если качество товара вас по каким-то причинам не устраивает.

У каждого регистратора SSL сертификатов условия разные и поэтому их всегда нужно уточнять перед тем, как купить SSL сертификат.

Поэтому я и перечислил все возможные «подводные камни», на которые следует обращать внимание. Если вы столкнётесь с ещё какими-то, то дайте мне об этом знать в комментариях :-)

Нужен ли HTTPS сайту?

nuzno-li-perekhodit-na-httpsПереход на HTTPS – это важный шаг для любого вебмастера. Пользователи привыкли видеть надежный замок рядом с адресной строкой и очень пугаются, когда браузеры говорят о небезопасности перехода. Для владельца сайта переход на https – это новый уровень безопасности и новые возможности для продвижения в поисковой выдаче.

Но так ли всё однозначно? Нужен ли HTTPS сайту вообще?

Для того, чтобы определиться с тем, стоит ли переходить на HTTPS, давайте ещё раз проанализируем все особенности данного протокола, а также достоинства и недостатки установки SSL сертификатов.

Плюсы HTTPS протокола следующие:

  1. Пользователь однозначно идентифицируется посредством SSL сертификата. Вы точно знаете, с кем соединены в момент передачи данных на сайте. Просто нажмите на замочек в адресной строке, и вы получите информацию о компании, которой был выдан данный сертификат. Это предотвращает случаи мошенничества и позволяет быстро выявлять правонарушителей.
  2. Данные защищаются от изменения в процессе передачи. Еще одной причиной, зачем нужен HTTPS, стало резкое увеличение количества взломов сайтов путем перехвата сообщений. Хакеры могли просматривать передаваемые между сервером и клиентом пакеты данных и инкапсулировать в них вредоносную информацию. Простыми словами, они видели, что запрашивает сервер, глушили ответ от клиента и направляли свои пакеты данных. Применение HTTPS полностью исключило подмену данных, поскольку в зашифрованном канале передается и контрольная сумма. Любая попытка изменить данные приведет к изменению целостности, которая будет замечена сервером.
  3. Относительно низкая стоимость SSL сертификатов, необходимых для подключения HTTPS. Цены стартуют с 10$ за год использования. К тому же постоянно проводятся различные акции, благодаря которым можно получить SSL сертификат бесплатно либо с огромной скидкой.
  4. Простота подключения HTTPS благодаря автоматизированным инструментам в панелях управления большинства современных хостингов. Благодаря ним в большинстве случаев установку SSL сертификата на сайт можно выполнить самостоятельно и нет необходимости в платных услугах профессионалов. Кроме того, по большинству моментов, возникающих в процессе инсталяции, вас смогут проконсультировать сотрудники хостингов и CA.
  5. Польза HTTPS для SEO. При одинаковых условиях, сайты на устаревшем HTTP будут ранжироваться хуже в поисковиках, чем с HTTPS, поскольку они вызывают меньше доверия. Официально использование HTTPS было включено в перечень факторов ранжирования еще в 2015 году. Представители Google настойчиво рекомендуют сайтам перейти на HTTPS как можно скорее, поскольку роль этого протокола в ранжировании будет только расти.
  6. Более точная аналитика. Мало кто знает, что HTTPS даёт возможность получать более точное количество переходов на сайт через различные сервисы аналитики, чем при использовании HTTP. Это связано с потерей информации о переходе при переключении с HTTPS на HTTP. Например, если подключение к вашему сайту происходит по стандартному HTTP протоколу, а к вам на сайт зашёл пользователь с HTTPS сайта, то переход будет засчитан как прямой, а не с другого ресурса.

Однако, за все эти преимущества HTTPS нужно рано или поздно платить. Поэтому при установке SSL сертификата на сайт нужно быть в курсе минусов HTTPS, которые могут привести к достаточно серьёзным проблемам:

  1. HTTPS использует SSL сертификаты, которые в большинстве случаев платные. Бесплатные варианты для основных сайтов и коммерческого использования не годятся.
  2. Неправильная установка SSL сертификата может полностью сделать сайт недоступным для поисковых роботов и пользователей, что чревато падением посещаемости и ухудшением позиций в ПС.
  3. Из-за ошибок конфигурирования HTTPS на сайте может возникнуть большое количество дублей страниц, либо некоторые могут остаться на HTTP, что также может стать поводом к снижению позиций в поисковой выдаче и появлением сообщения о небезопасности соединения в браузерах. Если ссылки внутри сайта были прописаны вручную, то после перехода на HTTPS без настройки редиректа они перестанут работать.
  4. Несмотря на простоту подключения SSL сертификата на сайт, которое можно выполнить самостоятельно, необходимы будут специальные настройки сайта, с которыми вы вряд ли справитесь самостоятельно без особых знаний (речь идёт о 301 редиректах и добавлении правил маршрутизации для HTTPS адресов).
  5. Компания, выдавшая SSL сертификат, может отозвать его в любой момент без объяснения причин, что также может обернуться снижением посещаемости ресурса в целом.
  6. Незначительно, но замедляется скорость подключения к сайту, поскольку для обработки запросов требуется расшифровка и шифрование ответов.

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

kupit-ssl-sertifikat-deshevoПри переводе существующего сайта на HTTPS существует большая вероятность ошибки, вследствие чего вы можете потерять из выдачи как некоторые страницы, так и весь сайт. Именно по этой причине я и не спешу переводить данный сайт на HTTPS. Тем более, что в сети сейчас полно ресурсов с высокой посещаемостью, которые по-старинке используют HTTP.

К тому же, HTTPS — это не панацея в вопросах безопасности. В 2011 году иранские хакеры в рамках централизованной атаки в ответ на санкции США взломали CA компаний Comodo и DigiNotar и похитили сотни тысяч сертификатов, которые можно использовать для подмены пакетов.

Не менее обескураживающим известием в этом году стало то, что среди похищенных сертификатов были принадлежащие ЦРУ, Моссаду, Британской разведке MI-6. Таким образом, защищенные ресурсы стали попросту бесполезными для этих известных организаций и стали угрожать комплексной безопасности, ведь хакеры стали рассылать по фальшивым сертификатам трафик, получая ответы от банков, почтовых и грузовых компаний, и других стратегически важных объектов.

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

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

nuzhen-li-https-sajtuТак что описанную выше информацию принимайте просто как известный факт :-) Также целью размещения списка проблем, к которым может привести неправильная настройка и установка SSL сертификатов, было замотивировать вас обращаться за помощью к профессионалам. Причём не только в области программирования, но и SEO, которые позволят вам сделать необходимые настройки с минимальным ущербом.

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

В случае же старта нового проекта я бы однозначно использовал HTTPS для передачи данных на самом старте, пока страницы не попали в индекс поисковиков и риск что-то поломать был бы минимален. Тем более, что цена SSL сертификатов сегодня достаточно смешная.

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

Ну, а в целом, осуществлять ли вам перевод сайта на HTTPS или нет — дело сугубо ваше личное. Моей целью было лишь призвать вас ответственно подходить к данному шагу, а не делать всё с бухты-барахты :-)

На этом у меня всё. Надеюсь, что статья помогла вам ответить на вопросы о том, что такое HTTPS, SSL, TLS, а также зачем нужен SSL сертификат, какими они бывают, где и как их можно купить.

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

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

Всем удачи и до новых встреч :-)

Делаем слайдер на JavaScript своими руками

js-slajderВсем привет! :-)

Поскольку я работаю Fullstack PHP разработчиком, то иногда приходится решать задачи, связанные с фронтэндом, несмотря на то, что я его недолюбливаю :-)

О моём отношению к всему, что связано с «прекрасным» вы, собственно говоря, могли оценить по дизайну данного сайта, который разрабатывался мною единолично :-)

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

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

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

Как сделать JavaScript слайдер: начало

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

Заказчикам всегда наплевать на то, как код написан, какая у него архитектура, главное — видеть результат!

В итоге, как вы поняли, перед тем, как написать слайдер на JavaScript без jQuery, я решил подыскать готовый и доработать его под свои нужды. Почему без jQuery? Да потому что на целевом ресурсе, куда я планировал подключать свой слайдер через сервис, вызов jQuery в коде был расположен позже скрипта, подключаемого сервисом. Поэтому jQuery конструкции в моём коде просто не воспринимались.

В качестве основы я взял этот JavaScript слайдер изображений — https://codepen.io/gabrieleromanato/pen/pIfoD.

Остановиться я решил именно на нём, т.к. его JS код был написан с применением принципов ООП и классы в нём основываются на прототипах, а не на банальных функциях.

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

Но, к сожалению, в современном мире мои позиции мало кто разделяет, т.к. данный язык развивается сумасшедшими темпами и предпринимает даже попытки завоевать умы бэкенд разработчиков с помощью Node.js как альтернативы Java, PHP, C#, Ruby и других монстров.

В итоге, чтобы банально не остаться без работы, приходится по-тихоньку с JavaScript разбираться. А в выбранной мною реализации слайдера на чистом JavaScript я встретил то, что, как вы поняли, презираю в данном языке. Поэтому я её и выбрал, чтобы был хоть какой-то повод поработать и разобраться с JavaScript ООП и прототипными классами — иначе я бы к ним добровольно никогда в жизни не прикоснулся бы :-)

На базе найденного мною кода мне необходимо было разработать слайдер на чистом JS во всплывающем окне (такую штуку ещё называют popup, попап и т.д.), который имел бы кнопки переключения слайдов и кликабельные индикаторы текущего слайда. Также нужно было сделать кнопку для закрытия данного окна.

Вот, что у меня получилось в итоге.

Делаем библиотеку JS слайдера

Сперва я решил всё реализовать по уму и сделать JavaScript слайдер для сайта в виде библиотеки, подключаемой на сайт одним-единственным скриптом, в котором будут вызываться компоненты слайдера, разбитые по подкаталогам. Назвать её я решил popupSlider.js в честь её изначального предназначения.

Её код можно найти на GitHub по этому адресу — https://github.com/Pashaster12/popupSlider.js

Структура библиотеки вышла следующая:

kak-sdelat-javascript-slajder-svoimi-rukami

Папка slides предназначена для картинок слайдов. В controls размещены картинки элементов управления JS каруселью (кнопки закрытия слайдера и переключения слайдов). А в assets — статические элементы JS слайдера: HTML разметка и файл с CSS стилями.

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

Я решил начать с HTML разметки нашей JS карусели картинок, которая в моём случае выглядит так:

<div id="cq-popup-bg"></div>
<div id="cq-popup">
    <a id="cq-popup-btclose" href="#"></a>
    <div id="slider">
        <div id="slider-wrapper">
            <div class="slide">
                <img src="slides/1.jpg" alt="" />
                <div class="caption">
                    <div class="caption-container">
                        Text 1
                    </div>
                </div>
            </div>
            <div class="slide">
                <img src="slides/2.jpg" alt="" />
                <div class="caption">
                    <div class="caption-container">
                        Text 2
                    </div>
                </div>
            </div>
            <div class="slide">
                <img src="slides/3.jpg" alt="" />
                <div class="caption">
                    <div class="caption-container">
                        Text 3
                    </div>
                </div>
            </div>
        </div>
        <div id="slider-nav">
            <a href="#" data-slide="0" class="current"></a>
            <a href="#" data-slide="1"></a>
            <a href="#" data-slide="2"></a>
        </div>
        <a href="#" class="horizontal-controls" id="prev"></a>
        <a href="#" class="horizontal-controls" id="next"></a>
    </div>
</div>

Для оформления слайдера на JavaScript в виде попапа я использовал следующие стили:

#slider {
    margin: auto;
    width: 600px !important;
    overflow: hidden;
}
#slider-wrapper {
    width: 9999px;
    height: 343px;
    position: relative;
    transition: left 400ms linear;
}
.slide {
    float: left;
    width: 600px;
    position: relative;
    overflow: hidden;
}
.caption {
    width: 600px;
    height: 110px;
    line-height: 1.5;
    font-size: 15px;
    font-weight: 300;
    text-align: center;
    color: #000;
    display:table;
}
.caption-container {
    display: table-cell;
    vertical-align: middle;
    padding: 0 20px;
}
#slider-nav {
    position: absolute;
    bottom: -36px;
    text-align: center;
    left: 50%;
    transform: translateX(-50%);
}
#slider-nav a {
    width: 8px;
    height: 8px;
    text-decoration: none;
    color: #000;
    display: inline-block;
    border-radius: 50%;
    margin: 0 5px;
    background-color: #fafafa;
}
#slider-nav a.current {
    background-color: #337ab7;
}
.horizontal-controls {
    position: absolute;
    display: inline-block;
    width: 12px;
    height: 20px;
    top: 50%;
    margin-top: -10px;
}
#prev {
    background: url(../controls/arrow_left_inactive.png);
    left: -40px;
}
#prev:hover {
    background: url(../controls/arrow_left_active.png);
}
#next {
    background: url(../controls/arrow_right_inactive.png);
    right: -40px;
}
#next:hover {
    background: url(../controls/arrow_right_active.png);
}
#cq-popup {
    width: 600px;
    z-index: 23;
    left: calc(50%);
    top: calc(50%);
    position: fixed !important;
    background-repeat: no-repeat;  
    background-position: right;
    background-color: #fff;
    font-family: "Roboto","Segoe UI","Helvetica","Georgia","Calibri","Verdana";
    transform: translate(-50%, -50%) scale(1);
}
#cq-popup .header {
    display: inline-block;
    font-size: 17px;
    font-weight: 500;
}
#cq-popup > div {
    width: 500px;
    font-size: 22px;
    line-height: 36px;
}
#cq-popup-btclose {
    text-decoration: none;
    position: absolute;
    right: -40px;
    top: 0;
    background: url(../controls/btn_delete_inactive.png);
    height: 16px;
    width: 16px;
}
#cq-popup-btclose:hover {
    background: url(../controls/btn_delete_active.png);
}
#cq-popup-bg {
    position: fixed;
    top:0; 
    width: 100%; 
    height: 100%;
    background: rgba(51,51,51,0.8);
    z-index: 22;
}

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

kak-napisat-js-slajder-svoimi-rukami-struktura

И HTML разметку, и CSS стили я вынес в отдельные файлы popupSlider.html и popupSlider.css, которые расположены в директории assets библиотеки слайдера на JavaScript. Я сделал это специально, чтобы пользователи при использовании данного кода могли без проблем корректировать разметку и оформление, не лазя в JS коде, где вынесенное нужно было бы прописать напрямую.

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

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

function Slider(element) {
    this.loadStatic();
    this.el = document.querySelector(element);
    this.init();
}

Slider.prototype = {
    init: function () {
        this.links = this.el.querySelectorAll("#slider-nav a");
        this.wrapper = this.el.querySelector("#slider-wrapper");
        this.nextBtn = this.el.querySelector("#next");
        this.prevBtn = this.el.querySelector("#prev");
        this.navigate();
    },
    navigate: function () {

        var self = this;

        for (var i = 0; i < this.links.length; ++i) {
            var link = this.links[i];
            link.addEventListener("click", function (e) {
                self.slide(this);
            });
        }

        self.prevBtn.style.display = 'none';

        self.nextBtn.addEventListener('click', function (e) {
            var currentSlideNumber = document.querySelector('#slider-nav a.current').getAttribute("data-slide");
            var nextSlide = document.querySelector('[data-slide="' + (parseInt(currentSlideNumber, 10) + 1) + '"]');

            nextSlide.click();
        }, false);

        self.prevBtn.addEventListener('click', function (e) {
            var currentSlideNumber = document.querySelector('#slider-nav a.current').getAttribute("data-slide");
            var prevSlide = document.querySelector('[data-slide="' + (parseInt(currentSlideNumber, 10) - 1) + '"]');

            prevSlide.click();
        }, false);

        self.close();
    },

    slide: function (element) {
        this.setCurrentLink(element);

        var index = parseInt(element.getAttribute("data-slide"), 10) + 1;
        var currentSlide = this.el.querySelector(".slide:nth-child(" + index + ")");

        this.wrapper.style.left = "-" + currentSlide.offsetLeft + "px";

        if (index < this.links.length)
            this.nextBtn.style.display = 'block';
        else if (index == this.links.length)
            this.nextBtn.style.display = 'none';

        if (index > 1)
            this.prevBtn.style.display = 'block';
        else if (index == 1)
            this.prevBtn.style.display = 'none';
    },

    setCurrentLink: function (link) {
        var parent = link.parentNode;
        var a = parent.querySelectorAll("a");

        link.className = "current";
        this.currentElement = link;

        for (var j = 0; j < a.length; ++j) {
            var cur = a[j];
            if (cur !== link) {
                cur.className = "";
            }
        }
    },

    loadStatic: function () {

        var self = this;

        var link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = 'assets/popupSlider.css';
        document.head.appendChild(link);

        var sliderHTML = '';

        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'assets/popupSlider.html', false);
        xhr.send();
        if (xhr.status != 200) {
            alert('Can not load the popupSlider.html. Got the error ' + xhr.status + ': ' + xhr.statusText);
        } else {
            sliderHTML = xhr.responseText;
        }

        var div = document.createElement('div');
        div.innerHTML = sliderHTML;
        document.body.appendChild(div);
    },

    close: function () {
        document.getElementById('cq-popup-btclose').onclick = function () {
            document.getElementById('cq-popup-bg').remove();
            document.getElementById('cq-popup').remove();
        }
    }
};

Немного комментариев по поводу приведённого кода. Содержимое файла popupSlider.js является одним JavaScript классом Slider, который, как и в PHP, содержит конструктор и методы класса. Только в JS определение конструктора, в отличие от PHP, является обязательным.

Конструктор определяется с помощью следующей конструкции:

function Slider(element) {
    //код конструктора
}

Внутри конструктора должны быть прописаны действия, которые будут выполняться при создании объекта класса.

Сами методы класса будут находиться внутри прототипа и будут доступны для всех экземпляров данного JavaScript класса. JS прототип в моём случае описывается следующей конструкцией:

Slider.prototype = {
    //методы
}

Вызываться за пределами тела класса они будут следующим образом:

var slider = new Slider();
slider.class_method();

А внутри самого кода класса доступен следующий способ:

this.class_method();

Главное только не забывать, что в JavaScript значение this зависит от контекста вызова, поэтому в телах некоторых методов, в которых нужно было вызывать методы и свойства класса, присутствует такая конструкция:

var self = this;
self.class_method(); //чтобы обратиться к методу, находящемся на уровень выше кода описываемого метода

Вроде обо всех нюансах написания кода я рассказал. Теперь пару слов о методах нашего JavaScript класса, внутри которых содержатся описания действий JS карусели картинок.

loadStatic()

Самый первый метод, вызывающийся при создании экземпляра класса в конструкторе. Отвечает за добавление в HTML кода страницы сайта HTML разметки слайдера и файла со стилями.

Сначала в памяти создаётся новый тэг link с помощью JavaScript функции document.createElement() и ему присваиваются значения всех необходимых атрибутов, в том числе и путь к CSS файлу со стилями JS слайдера. И, в конце-концов, он добавляется в HTML страницы с помощью JavaScript метода appendChild() в конец секции head, где и должны подключаться CSS файлы стилей.

Далее мы делаем то же самое для файла с HTML разметкой нашего слайдера на чистом JavaScript. Вот только здесь есть маленький нюанс: просто так HTML файл внутри такого же подключить нельзя, как мы сделали это с CSS файлом. Для этого есть специальные библиотеки, например, для того, чтобы подключить HTML в HTML, отлично подходит либа от w3.org — https://www.w3schools.com/howto/howto_html_include.asp

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

В итоге, я решил получать содержимое HTML файла внутри JavaScript кода и загружать его в новый div элемент, создаваемый в памяти, как я делал это ранее для подключения CSS файла в JavaScript. Сгенерированный элемент подключается в самый конец секции body HTML кода страницы сайта.

Если хотите вставить div с разметкой слайдера не просто в конец body, а в какой-то конкретный контейнер, то можете вместо следующего кода:

var div = document.createElement('div');
div.innerHTML = sliderHTML;
document.body.appendChild(div);

Прописать следующее, указав нужный идентификатор целевого контейнера (в моём случае HTML JS слайдера будет расположен в элементе с id popupSlider):

var target = document.querySelector( "#popupSlider" );
target.innerHTML = sliderHTML;

init()

Метод, который вызывается в конструкторе после loadStatic(), и нужен для инициализации свойств класса, соответствующих основным HTML элементам, к которым мы будем обращаться в следующем коде.

В конце вызывается метод navigate().

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

Сам JavaScript код смены слайдов для удобства я вынес в отдельный метод slide(), а в данном я только навешиваю его на событие click для каждой круглой кнопки в цикле.

При клике на кнопки «предыдущий слайд»/»следующий слайд» я, как видите, решил всего лишь эмулировать нажатие на соответствующий кружочек, определяя нужный относительно текущего, у которого имеется CSS класс current.

slide(element)

Метод, «отвечающий за магию» самой JavaScript карусели, в котором содержится код, меняющий слайды местами. В самом начале вызывается метод setCurrentLink(), о котором мы поговорим чуточку позже.

В качестве входного параметра в него передаётся объект кнопки навигации JS слайдера в виде кружочка.

Само переключение слайдов работает следующим образом:

  1. Все слайды у нас оформлены в виде блоков одинаковых размеров, идущих друг за другом. Окно слайдера — это лишь видимая часть элемента, содержащего все слайды.
  2. Мы определяем смещение левого края текущего слайда от левого края родительского элемента с помощью свойства offsetLeft.
  3. И сдвигаем родительский элемент на это значение, чтобы в окне слайдера у нас отображался необходимый элемент.

В конце метода описано поведение для кнопок «предыдущий слайд»/»следующий слайд», оформленных в виде стрелок влево/вправо соответственно. Если текущий слайд — первый из всего списка, то кнопка перехода к предыдущему слайду скрывается. Если последний, то убираем кнопку перехода к следующему слайду.

setCurrentLink(link)

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

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

Логика выделения текущего элемента проста:

  1. Получаем объект родительского элемента, которым в нашем случае выступает контейнер с идентификатором slider-nav.
  2. Получаем все навигационные элементы в виде массива ссылок.
  3. Выделяем элемент, полученный на входе, путём добавления ему классу current.
  4. В цикле перебираем все навигационные элементы и у всех, кроме текущего, очищаем значение класса. Это нужно для того, чтобы снять выделение с элемента, которым был текущим до данного вызова функции.

close()

Самый последний метод класса, в котором определяется действие при нажатии на кнопку закрытия слайдера в виде крестика. Здесь, собственно говоря, код самый понятный из всего, содержащегося в классе JS слайдера.

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

Сам метод вызывается внутри описанного ранее navigate(), который содержит в себе все сценарии действий, происходящих на нашем JavaScript слайдере.

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

document.getElementById('cq-popup-bg').onclick = function () {
document.getElementById('cq-popup-bg').remove();
document.getElementById('cq-popup').remove();

JavaScript слайд шоу на базе разработанной библиотеки

Иногда на практике может потребоваться сделать JS карусель с прокруткой, которую часто называют слайд шоу. В моём случае этого не требовалось, но я всё же решил сделать такую на базе итогового кода библиотеки для случая, когда это может пригодиться.

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

Для автоматической прокрутки слайдов я добавил в самый конец своего класса следующий метод:

slideShow: function (timeout) {
    var sliderCount = this.links.length;
    var self = this;

    this.slideCycle = setInterval(function () {
        var currentSlideNumber = document.querySelector('#slider-nav a.current').getAttribute("data-slide");
        var slideId = parseInt(currentSlideNumber, 10) + 1;
        self.slide(document.querySelector('[data-slide="' + (sliderCount == slideId ? 0 : slideId) + '"]'));
    }, timeout);
}

Что здесь происходит — думаю, понятно. Для создания данного метода я скопировал код из события клика на кнопки ручного переключения слайдов и разместил его внутри вызова JavaScript функции setInterval(), которая выполняет указанное действие через заданный промежуток времени.

Сценарий действия передаётся первым аргументом в виде анонимной функции, а временной интервал — вторым, который я решил сделать в виде переменной, значение которой передаётся при вызове slideShow().

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

Ну, и для того, чтобы данный код заработал, сам метод необходимо вызвать. Я решил сделать это всё в том же navigate(), который как раз и является сборником всяких сценариев. Вызов я разместил в самом конце, передав в качестве аргумента значение временного интервала для автоматической смены слайдов в нашем JS слайд шоу (я выбрал 2000 милисекунд или 2 секунды, вы можете по необходимости изменять это число):

self.slideShow(2000);

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

По идее, всё должно работать. Если нет — изучайте ошибки в консоли браузера и делитесь ими в комментариях.

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

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

Для прерывания автоматического показа слайдов JavaScript карусели я решил воспользоваться стандартной JS функцией clearInterval(), которой в качестве аргумента передаю идентификатор временного интервала, возвращаемого функцией setInterval() при его установке.

В итоге, получился следующий код, который я решил не оформлять отдельным методом:

clearInterval(self.slideCycle);

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

link.addEventListener("click", function (e) {...});

self.prevBtn.addEventListener('click', function (e) {...});

self.nextBtn.addEventListener('click', function (e) {...});

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

Интеграция JavaScript слайдера на сайт

Итак, наш слайдер на чистом JS готов. Осталось теперь только подключить его на сайт.

Для этого необходимо выполнить последовательно следующие шаги, которые являются стандартными действиями при интеграции каких-либо сторонних JavaScript библиотек вообще.

Шаг 1. Копируем файлы библиотеки к себе на сайт в отдельный каталог.
Шаг 2. Добавляем следующий код в HTML страниц, на которых необходимо будет отображение слайдера, разместив его перед закрывающимся тэгом body:

<script type="text/javascript" src="/каталог_слайдера/popupSlider.js"></script>

Шаг 3. Размещаем следующий код вызова JS карусели в каком-либо существующем JavaScript файле, который подключается на странице после подключения самого слайдера:

var aSlider = new Slider("#slider");

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

Добавление новых слайдов в JavaScript карусель

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

А затем в коде файла assets/popupSlider.html добавить новый блок в контейнер с id slider-wrapper:

<div class="slide">
    <img src="slides/new_slide.jpg" alt="" />
    <div class="caption">
        <div class="caption-container">
           Text
        </div>
    </div>
</div>

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

Также необходимо будет добавить новый элемент навигации в виде кружочка, т.к. на данный момент автоматическое его добавление пока не реализовано. Для этого нужно будет добавить следующий код в контейнер с id slider-nav, прописав его в самом конце:

<a href="#" data-slide="id"></a>

Значение атрибута data-slide должно быть больше самого большого у остальных элементов. Достаточно всего лишь увеличить максимальное текущее на единицу.

Упаковка JS карусели в единый скрипт

Всё, слайдер на JavaScript готов и подключен. Я лично рекомендую использовать данный вариант на практике, если он вам вообще пригодится :-)

Для ускорения работы его, кстати, можете ещё дополнительно сжать статические компоненты: CSS, HTML и JavaScript файлы. Я не стал этого делать и предлагать вам минифицированный код, потому что систем сборок фронтэнда сейчас очень много: Gulp, Grunt, Webpack и другие. И у каждой из них свои алгоритмы сжатия и подключения файлов.

К тому же, минифицированные результаты на разных ОС могут работать по-разному. В общем, причин много.

Да и сами исходники у меня вышли, я считаю, не такие уж тяжеловесные, что нуждаются в данной процедуре. Но если же вам они будут необходимы, то настройте минификацию самостоятельно с учётом вашей ОС и сборщика.

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

Так вот, в завершение своего сегодняшнего повествования я решил поделиться с вами финальной версией своей JavaScript карусели, которую я использовал на практике. Возможно, кому-то данный способ будет полезен. Он также пригодится тем, кто будет подключать предоставленную мною библиотеку через системы сборки Webpack, Gulp, Grunt и при этом столкнётся с проблемой правильности файловых путей.

Тогда вариант единого скрипта JavaScript карусели вам придётся как нельзя кстати, т.к. весь контент будет содержаться прямо в нём, в том числе и HTML/CSS код, который в случае библиотеки хранится в отдельных файлах.

Скрипт в моём случае состоит из двух частей. В первой части располагалось содержимое файла popupSlider.js, которое я второй раз не буду приводить. Вставьте его самостоятельно, убрав из кода класса описание метода loadStatic() и его вызов, т.к. они нам не понадобятся.

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

Там у нас будет происходить добавление на страницу HTML/CSS кода JS карусели и создание объекта класса Slider, что равносильно активации самого слайдера.

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

/* содержимое popupSlider.js без описания метода loadStatic() и его вызова */

document.addEventListener('DOMContentLoaded', function(){
    var str = '\
         <style>\
             /*css код*/
         </style>\
         /* html код */
         ';

    var div = document.createElement('div');
    div.innerHTML = str;
    document.body.appendChild(div);

    var aSlider = new Slider("#slider");

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

Если у вас таких сложностей нет, то можете ничего не менять, но не забыть скопировать каталоги slides и controls библиотеки на сервер и указать правильные пути к ним.

Самописный JS слайдер — перспективы развития

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

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

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

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

  1. сделать внешний конфиг, чтобы можно было удобно настраивать слайдер;
  2. сделать возможность встраивания слайдера внутрь страницы (сейчас оформлен только в виде попапа);
  3. асинхронная загрузка HTML кода (сейчас сделана синхронная, которая многими браузерами помечается как устаревший вариант);
  4. оформить библиотеку в виде пакета, NPM, Bower или другого пакета, чтобы его можно было устанавливать и оперировать зависимостями с помощью пакетных менеджеров;
  5. сделать вёрстку адаптивной для использования JS карусели на различных устройствах;
  6. сделать переключение слайдов по событию Swipe для мобильных пользователей.

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

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

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

У меня всё! Всем добра! :-)

Блокировка ВК в Украине: 3 совета вебмастерам

blokirovka-vk-v-ukraineВсем привет!

С 2014 года, когда начался конфликт между Россией и Украиной, я всячески стараюсь избегать тем политики. Но, тем не менее, как бы мы от политики не ограждались, но сделать это на 100% всё равно никогда не получится, т.к. вся наша жизнь подчинена её законам.

Особенно правоту данного высказывания испытали на себе все украинские пользователи Интернет 16 мая 2017 года, когда президент Украины Пётр Порошенко подписал указ о блокировке сайтов Вконтакте, Одноклассники, Яндекс, Mail.ru и прочих российских ресурсов на территории Украины.

Казалось бы: ничего страшного не произошло, подумаешь — нельзя будет несколькими сайтами пользоваться. Тем более, что у всех них есть разрешённые альтернативы да и VPN клиенты никто не отменял, с помощью которых можно обходить блокировки по IP адресам.

Но сегодня речь пойдёт не о том, как обойти блокировку ВК, Одноклассников, Яндекса и прочих ресурсов пользователям Украины, чтобы продолжать пользоваться их контентом.

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

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

Всему виной всевозможные виджеты Вконтакте: сообществ, комментариев, лайков и т.д., а также используемые вебмастерами скрипты сбора статистики Яндекс.Метрика и Mail.ru. И ладно бы они просто не загружались, а то и контент сайта делают недоступным.

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

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

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

Технические причины проблем сайтов из-за блокировки ВК в Украине

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

  1. Удобство использования ресурса пользователями — достигается с помощью виджетов комментариев и авторизации, благодаря которым ваши посетители, имеющие аккаунты в социальных сетях, могут оставлять отзывы без необходимости заполнения контактной информации и внутренней регистрации на вашем сайте.
  2. Социальная активность — с помощью виджетов сообществ можно делиться с вашими подписчиками самой разнообразной информацией, не публикуемой на сайте, в том числе организовывать в сообществах опросы и обсуждения, делясь их результатами через виджеты.
  3. Увеличение аудитории сайта — благодаря виджетам, позволяющим поделиться страницами Вашего сайта в социальных сетях с другими пользователями.

И, чем больше социальная сеть, тем в большей степени перечисленные функции виджетов выполняются. К примеру, Вконтакте, как самая популярная отечественная социальная сеть в день её запрета на территории Украины имела посещаемость 18 миллионов украинских пользователей в день.

К слову, всё население Украины на данный момент составляет 42 миллиона.

Но, все перечисленные преимущества утратили свою значимость в мае 2017, когда вступил в силу запрет ВК в Украине и ряда других ресурсов. И самое страшное, что помимо утраты функций социальных виджетов сайты стали терять ещё и посетителей, т.к. мало кто будет ждать полной загрузки сайта.pochemu-ne-zagruzhaetsya-sajt-iz-za-vidjetov-soobschestv

Самое обидное, что из-за санкций пострадали не только украинские пользователи Интернет, но и вебмастера, сайты которых эти люди посещали.

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

Всему виной адрес API ВК, которое содержит в своём URL доменное имя самого заблокированного ресурса — vk.com/js/api/openapi.js?150. Поэтому виджеты и не могут загрузиться.

А, поскольку, виджеты Вконтакте загружаются по меру загрузки страницы сайта, то всё время, которое браузер ожидает ответа от заблокированного vk.com, содержимое сайта остаётся недоступным.

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

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

Но не время горевать по общей доступности заблокированных ресурсов, а нужно учитывать реалии и учиться существовать в современных условиях. Поэтому я приведу вам несколько способов, как можно сохранить работоспособность ресурсов и даже увеличить её, несмотря на блокировку ВК в Украине.

Оптимизация сайтов вследствие запрета ВК в Украине

Сразу скажу, что при перечислении мер оптимизации среди них вы не встретите самую радикальную — отказ от подобных сервисов вообще. Выход есть всегда :-)

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

Так что будем обходиться малой кровью. Тем более, что это возможно.

Асинхронная загрузка кода

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

Здесь, как ни удивительно, виноватыми снова выступают разработчики Вконтакте, которые реализовали исключительно синхронную загрузку JavaScript кода.

Синхронная загрузка, для тех, кто не в курсе — это выполнение JavaScript сценария по мере загрузки всего сайта. Если синхронный скрипт расположен в шапке сайта между тэгами head, то остальной код не обработается браузером до тех пор, пока он не выполнится.

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

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

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

Для сообщения браузеру о том, что определённый элемент нужно загружать асинхронно, в конце его открывающего HTML тэга нужно поставить атрибут async или defer, если хотите, чтобы элемент загрузился после завершения загрузки остальных.

Данный метод хорошо работает в случаях подключения на страницу готовых элементов (например, у Facebook при размещении виджета в виде iframe), однако, в случае с виджетами Вконтакте этот номер не проходит, т.к. на момент загрузки виджета браузером он ещё не загрузился по API ВК, которое недоступно.

alternativy-vidjeta-gruppy-vkontakte-na-sajtПоэтому нужно программно определить момент, когда придёт ответ от API VK, и только тогда уже загружать его в элемент виджета. Для этих целей существует масса готовых скриптов, поэтому я не посчитал нужным писать его заново.

Для асинхронной загрузки виджетов Вконтакте на данном сайте лично я пользовался следующим кодом — http://xpro.su/php/async_widgets-1. Скрипт рабочий, поэтому рекомендую :-)

Автор, как я понял, за основу взял код асинхронной загрузки VK OpenAPI, с которым вы можете познакомиться по данной ссылке — https://vk.com/dev/openapi

Ну, и ещё автор дописал код для работы в Internet Explorer старых версий, которым я решил пренебречь ввиду древности данной технологии.

В итоге, мой слегка дополненный вариант асинхронного виджета Вконтакте выглядел так:

<div id="vk_groups"></div>
<script type="text/javascript">
    var VK_loader = function () {
        var oHead = document.getElementsByTagName("head")[0];
        var oScript = document.createElement("script");
        oScript.type = "text/javascript";
        oScript.async = true;
        oScript.src = "http://vk.com/js/api/openapi.js?150";
        oHead.appendChild(oScript);
        oScript.onload = function () {
            VK.Widgets.Group(
                    "vk_groups",
                    {
                        mode: 0,
                        width: "286",
                        height: "320",
                        color1: 'FFFFFF',
                        color2: '444444',
                        color3: '00a1e0'
                    },
                    номер_группы
                    );
        }
    };
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", function () {
            document.removeEventListener("DOMContentLoaded", arguments.callee, false);
            VK_loader();
        }, false);
    }
</script>

При реализации кода из приведённой статьи на своём сайте я ещё заметил, что он прекрасно работает без указанного в оригинале кода:

oScript.onload = function() {
         VK.init({apiId: ID_сайта_ВКонтакте, onlyWidgets: true});//лишний код
         VK.Widgets.Group("vk_groups", {mode: 0, width: 200, height: 250}, номер_группы);
       }

Поначалу я никак не мог понять, что это за ID_сайта_Вконтакте, т.к. автор не указал, где его брать. В итоге я отыскал, где взять данный ключ. Им оказался ID приложения Вконтакте, которое создаётся для доступа к сайтам через OpenAPI.

Создать приложение ВК для получения необходимого ключа можно здесь — https://vk.com/editapp?act=create
А получить ключ существующего приложения Вконтакте можно вот здесь — https://vk.com/apps?act=manage

Но, как выяснилось, код работал при указании вместо ID_сайта_ВКонтакте любого числа. В итоге я вообще решил убрать данную строку во избежания недоразумений.

Кстати, итоговый код загрузки виджета группы Вконтакте для сайта можете использовать для асинхронной загрузки любых виджетов и компонентов, использующих JavaScript код. Для этого прочитайте комментарии под статьёй, из которой я его изначально позаимствовал, где автор рассказывает, как добавить в данный блок Яндекс.Метрику и другие скрипты.

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

Но у асинхронной загрузки есть и минус — несмотря на то, что сайт загрузится без проблем, вместо виджета ВК в конечном итоге будет пустое место, т.к. его API в принципе недоступно.

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

Поиск альтернатив заблокированным ресурсам

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

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

Вместо того же ВК можно пользоваться разрешённым в Украине и не менее крупным Facebook, у которого есть аналогичные виджеты сообществ и комментариев. Или даже Одноклассниками, которые, несмотря на аналогичный с ВК запрет, смогли организовать своё АПИ так, что виджеты грузятся без проблем благодаря URL API, отличному от основного сайта — https://connect.ok.ru/connect.js

Ещё и сам код виджета у одноклассников загружается асинхронно, за что честь и хвала их администрации и разработчикам. Не знаю, когда именно были добавлены эти новшества — то ли как средство обхода блокировки вконтакте в Украине, то ли существовали с самого начала, но на выходе мы имеет одно — Одноклассники здесь обошли ВК, и это факт :-)

Жаль только, что аудитория Одноклассников несколько иная, чем у ВК, да и не такая многочисленная — накануне запрета посещаемость украинских пользователей была 5 миллионов в день.

Или ещё можно воспользоваться новым детищем Павла Дурова Telegram, который, кстати, неплохо набрал обороты после майских событий.

Ну, а Яндекс.Метрику и счётчики Mail.ru можно заменить на Google Analytics, LiveInternet и Рамблер ТОП100.

Хотя, правды ради, нужно сказать, что данные компании переработали свои инструменты с вводом запрета ВК в Украине и если поначалу продукты Mail.ru тормозили загрузку сайта, то, буквально вчера я рискнул снова установить себе счётчик и проверить состояние сайта при этом — никаких проблем с загрузкой не произошло.

С Яндекс.Метрикой у меня же изначально никаких проблем не наблюдалось, несмотря на жалобы других вебмастеров. Ну, и сейчас они также не возникли. Правда, показатели посещаемости по Яндекс.Метрике примерно на 30 посетителей в день меньше, чем у LiveInternet. Не знаю, с чем это связано — то ли из-за санкций трафик стал учитываться по-другому, то ли так было всегда, просто я этого не замечал :-)

Но, в любом случае, какими бы ни были привлекательными альтернативы, но они всё же неспособны затмить оригинал. Ярким доказательством данной идеи стало прекращение работы инновационной украинской социальной сети Ukrainians, ставящей своей задачей стать заменителем ОК и ВК для жителей Украины.

В итоге, она просуществовала около 3 месяцев, и её организаторы заявили, что вынуждены признать тот факт, что «Facebook, Instagram, VK и Однокласники (доступ через специальные каналы) не оставляют на рынке ниши для ещё одной социальной сети».

Да, что бы кто не говорил, но люди не способны так быстро отказаться от своих привычек…

У большинства вебмастеров до ввода блокировки Вконтакте в Украине паблик ВК был основным инструментом социальной активности и имел множество подписчиков.

И теперь вдруг он стал недоступен для половины подписчиков. Что же теперь — отказываться от него насовсем и начинать развивать сообщества в Facebook или Telegram? Некоторые так и сделали, но их не большинство.

Лично я не был готов распрощаться со своим пабликом ВК и его аудиторией, формировавшейся не один год, поэтому нашёл ещё одно средство решения проблемы, вызванной запретом Контакта, Одноклассников и прочих российских ресурсов в Украине.

Загрузка необходимого виджета

Конечным средством оптимизации данного сайта в связи с суровыми политическими реалиями стало внедрение стратегии «И нашим, и вашим» :-)

Согласно ей я решил показывать украинским пользователям виджет сообщества в Facebook, а всем остальным, у кого ВК не заблокирован — виджет Вконтакте. Как определить, откуда к вам зашёл пользователь? Просто — по его сетевому IP адресу.

Алгоритм простой — получаем IP клиента, определяем страну, и на основании результата отображаем нужный виджет.

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

Поскольку сайт у меня разработан на WordPress, то код из статьи по ссылке я оформил отдельной функцией, которую вынес в functions.php моей темы:

function checkCountryByIp()
{
    $client  = @$_SERVER['HTTP_CLIENT_IP'];
    $forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
    $remote  = @$_SERVER['REMOTE_ADDR'];
    $result  = array('country'=>'', 'city'=>'');

    if(filter_var($client, FILTER_VALIDATE_IP)) $ip = $client;
    elseif(filter_var($forward, FILTER_VALIDATE_IP)) $ip = $forward;
    else $ip = $remote;

    $ip_data = @json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=".$ip));
    if($ip_data && $ip_data->geoplugin_countryName != null)
    {
        $result = $ip_data->geoplugin_countryCode;
    }

    return $result;
}

Как вы видите, я получаю код страны по IP адресу пользователя. Теперь мне нужно, используя его, загружать на страницу нужный виджет.

Для этого я в сайдбаре, где у меня располагается виджет сообществ для внешних сайтов, прописал следующую конструкцию:

<div class="vk-widget" <?php if(checkCountryByIp() == 'UA'){ ?> style="height: 178px;" <?php } ?>>
    <?php if(checkCountryByIp() != 'UA'){ ?>
        <script type="text/javascript" src="//vk.com/js/api/openapi.js?146"></script>
        <!-- VK Widget -->
        <div id="vk_groups"></div>
        <script type="text/javascript">
            VK.Widgets.Group("vk_groups", {
                    mode: 0,
                    width: "286",
                    height: "320",
                    color1: 'FFFFFF',
                    color2: '444444',
                    color3: '00a1e0'
                }, 105617374);
        </script>
    <? }else{ ?>
        <iframe src="https://www.facebook.com/plugins/page.php?href=https%3A%2F%2Fwww.facebook.com%2Fcccpblog
                &tabs&width=286&height=170&small_header=true&adapt_container_width=true&hide_cover=false
                &show_facepile=true&appId" width="286" height="170"
                style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" async>
        </iframe>
    <?php } ?>
</div>

Как видите, я проверяю код страны, возвращённый функцией checkCountryByIp(). Если он не равен ‘UA’, то добавляю виджет группы ВК. В противном случае отображается виджет Facebook.

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

Не забудьте только вместо моих виджетов сообществ для внешних сайтов установить свои. Если вы вдруг не знаете, где взять код, чтобы добавить виджет группы на сайт, то перейдите по этой ссылке и создайте его, указав id своей группы — https://vk.com/dev/Community

Виджет группы Facebook (который теперь стал называться виджетом страницы) можно взять здесь — https://developers.facebook.com/docs/plugins/page-plugin/

Я уже думал, что с установкой приведённого кода мои искания поисков обхода блокировки ВК в Украине подошли к концу, но, поскольку у меня на сайте установлен плагин серверного кэширования, из-за которого вместо виджета Facebook иногда всё-таки пытался загрузиться ВК и контент сайта снова не догружался, мне пришлось слегка подкорректировать скрипт.

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

<div class="vk-widget" <?php if(checkCountryByIp() == 'UA'){ ?> style="height: 178px;" <?php } ?>>
    <?php if(checkCountryByIp() != 'UA'){ ?>
        <div id="vk_groups"></div>
    <? }else{ ?>
        <iframe src="https://www.facebook.com/plugins/page.php?href=https%3A%2F%2Fwww.facebook.com%2Fcccpblog
                &tabs&width=286&height=170&small_header=true&adapt_container_width=true&hide_cover=false
                &show_facepile=true&appId" width="286" height="170"
                style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" async>
        </iframe>
    <?php } ?>
</div>

Таким «куцым» он вышел потому, что весь JavaScript код асинхронной загрузки виджета ВК на сайт я решил вынести в отдельный скрипт, который подключал на сайт в футере:

if (document.getElementById("vk_groups")) {
    var VK_loader = function () {
        var oHead = document.getElementsByTagName("head")[0];
        var oScript = document.createElement("script");
        oScript.type = "text/javascript";
        oScript.async = true;
        oScript.src = "http://vk.com/js/api/openapi.js?150";
        oHead.appendChild(oScript);
        oScript.onload = function () {
            VK.Widgets.Group(
                    "vk_groups",
                    {
                        mode: 0,
                        width: "286",
                        height: "320",
                        color1: 'FFFFFF',
                        color2: '444444',
                        color3: '00a1e0'
                    },
                    105617374
                    );
        }
    };
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", function () {
            document.removeEventListener("DOMContentLoaded", arguments.callee, false);
            VK_loader();
        }, false);
    }
}

Сюда, помимо описанного ранее кода, я решил добавить проверку на существование контейнера, в который загружается виджет ВК по АПИ, т.к. скрипт загружается даже в случае загрузки виджета Фейсбук, когда контейнера на странице нет физически, в результате чего браузер выдаёт ошибку в консоли.

Несмотря на то, что приведённый выше скрипт я использовал для установки виджетов соцсетей на своём WordPress сайте, он подойдёт для любого ресурса, разработанного на языке PHP, т.к. никаких специальных конструкций WordPress API я при его разработке не использовал.kak-dobavit-vidjet-vkontakte-i-fejsbuk-na-sajt-po-ip

Если же вы не хотите морочиться установкой кода на сайт, то можете воспользоваться готовыми решениями в виде плагинов для CMS. Например для определения страны и города по IP на WordPress можете воспользоваться WT GeoTargeting — https://ru.wordpress.org/plugins/wt-geotargeting/

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

Думаю, что по ходу чтения материала вы догадались, почему в теме статьи делается акцент именно на блокировку ВК в Украине, хотя под санкции попал и ряд других популярных ресурсов? Всё просто: в отличие от своих собратьев по санкциям на данный момент (а это уже спустя полгода) только Вконтакте палец о палец не ударил, чтобы сделать свои виджеты доступными для заблокированных пользователей.

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

Но разработчики ВК почему-то до сих пор ничего этого не сделали, несмотря на то, что, регулярно выпускают новые версии API.

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

На этом у меня всё. Пишите свои отзывы о статье в комментариях и делитесь ей со своими друзьями в социальных сетях с помощью кнопочек под публикацией. Надеюсь, что материал был вам полезен :-)

До новых встреч!

Определение города по IP в PHP: 3 способа

opredelenie-goroda-po-ip-v-phpВсем привет!

Не скажу, что часто, но время от времени у разработчиков появляется необходимость определения города по IP в PHP скрипте.

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

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

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

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

PHP GeoIP — стандартный функционал стороннего производства

Я специально так озаглавил описание первого способа. Дело в том, что в самом PHP определить город и страну по IP адресу нельзя — язык не обладает для этого необходимыми инструментами.
Зато в официальной документации есть подсказка, как это сделать.

PHP GeoIP — это сторонняя библиотека, которую необходимо подключать дополнительно, несмотря на то, что описание функций, входящих в неё, является частью официальной документации PHP — http://php.net/manual/ru/ref.geoip.php

В принципе, мотивы разработчиков PHP вполне понятны.

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

Во-вторых, GeoIP PHP работает на базе перечня IP адресов, соответствующих определённым странам и городам. Поэтому GeoIP PHP требует постоянной поддержки и расширения/модернизации существующей базы, что являлось бы лишней головной болью разработчиков PHP.

Ну, и в-третьих, определение города по IP в PHP — возможность достаточно редко используемая на практике.

В итоге, из-за этих факторов PHP GeoIP является сторонним расширением, поддержкой которого и созданием API для интеграции на существующих сайтах занимается компания MaxMind, ссылка на которую присутствует в описании данной библиотеки.

Я не буду заниматься описанием процесса её установки на сервер, т.к. я сам на практике этим не занимался, и в Интернете на данный момент полно мануалов по установке PHP GeoIP как на Linux, так и на Windows сервера.

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

  1. Доступ к базе полной информации по IP адресам, предоставляемой компанией MaxMind, платный. Причём, сумма в долларах, как ни странно :-) Бесплатно доступны лишь существенно урезанные варианты — http://dev.maxmind.com/geoip/geoip2/geolite2/
  2. Учитывая, что PHP GeoIP — стороннее расширение, его необходимо будет отдельно устанавливать на сервер, что при условии использования shared хостинга может стать затруднительным мероприятием. Можно конечно, обратиться в техподдержку, но не факт, что вам помогут. Мне, например, при просьбе установить Sphinx отказали.

Определение города по IP в PHP с помощью альтернативных библиотек

Ещё один способ узнать город по IP в PHP скрипте — это использование альтернативных серверных библиотек и баз информации для IP адресов, отличных от MaxMind.

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

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

Примером такой библиотеки является предоставляемая сервисом db-ip.com.

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

Кстати, указанный мною сервис предоставляет не только свою PHP библиотеку для получения гео данных по IP клиентов, но и доступ к базам информации по адресам. Так что, в принципе, никто вам не мешает использовать их в PHP GeoIP, чтобы использовать его API, но информацию брать из других источников.

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

Как определить город по IP в PHP online

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

Он заключается в использовании API онлайн сервисов, которые позволяют получать данные по IP адресу в режиме онлайн.

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

Для того, чтобы получить необходимую информацию по IP, достаточно всего лишь отправить запрос на определённый URL и обработать ответ.

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

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

В итоге, я отыскал то, что мне было необходимо, чем и хочу с вами определиться — http://www.geoplugin.com/

Данный сервис позволяет как определять город и другую информацию по IP на сайте сервиса, так и производить это из кода. Далее я приведу пример определения страны по IP в PHP скрипте с помощью geoplugin.com. Определение IP в PHP коде осуществляется с помощью кода, описанного в статье по ссылке.

<?php

$client  = @$_SERVER['HTTP_CLIENT_IP'];
$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote  = @$_SERVER['REMOTE_ADDR'];
$result  = array('country'=>'', 'city'=>'');

if(filter_var($client, FILTER_VALIDATE_IP)) $ip = $client;
elseif(filter_var($forward, FILTER_VALIDATE_IP)) $ip = $forward;
else $ip = $remote;

$ip_data = @json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=".$ip));    
if($ip_data && $ip_data->geoplugin_countryName != null)
{
    $result = $ip_data->geoplugin_countryCode;
}

echo $result;

?>

Как видите, суть приведённого кода заключается в определении IP адреса клиента, причём учитывается возможность его подключения через прокси, и отправке запроса по API GeoPlugin с дальнейшим декодированием и анализом результатов.

В моём примере, как я уже и говорил, результатом работы данного скрипта будет являться код страны клиента сайта. Вообще, полный список возвращаемых параметров выглядит так (для примера решил взять IP Новосибирской области РФ):

{
  "geoplugin_request":"195.208.128.3",
  "geoplugin_status":200,
  "geoplugin_credit":"Some of the returned data includes GeoLite data created by MaxMind, available from <a href='http:\/\/www.maxmind.com'>http:\/\/www.maxmind.com<\/a>.",
  "geoplugin_city":"Novosibirsk",
  "geoplugin_region":"Novosibirsk",
  "geoplugin_areaCode":"0",
  "geoplugin_dmaCode":"0",
  "geoplugin_countryCode":"RU",
  "geoplugin_countryName":"Russian Federation",
  "geoplugin_continentCode":"EU",
  "geoplugin_latitude":"55.09",
  "geoplugin_longitude":"82.6519",
  "geoplugin_regionCode":"53",
  "geoplugin_regionName":"Novosibirsk",
  "geoplugin_currencyCode":"RUB",
  "geoplugin_currencySymbol":"&#1088;&#1091;&#1073;",
  "geoplugin_currencySymbol_UTF8":"\u0440\u0443\u0431",
  "geoplugin_currencyConverter":58.9289
}

Как видите, данный сервис использует упоминаемый ранее MaxMind (параметр geoplugin_credit), но платную информацию или нет — сложно предположить. С одной стороны, ссылка на источник говорит о том, что используется бесплатный доступ к БД IP, но, с другой, мы видим не только страну и город, но и ещё много всякой информации, включая город, географические координаты координаты (langitude, latitude), текущую валюту и даже её курс.

Так что данный сервис можно назвать PHP GeoIP онлайн. Единственное его отличие от серверного аналога — то, что он получает информацию по IP немного медленнее за счёт отсутствия серверного кэширования. Но это ещё не значит, что его нет на самом сервере GeoPlugin 😉 Так что недостаток этот, скорее, символический.

В любом случае, разработчики GeoPlugin заслуживают на аплодисменты, а, в особенности, ещё и за то, что они даже не захламили своё сайт контекстной рекламой. Т.е. как они вообще выживают — непонятно. Единственный способ сказать им «спасибо» — это пожертвования на PayPal счёт.

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

На этом у меня всё. Пишите ваши отзывы о статье в комментариях ниже и не забывайте делиться записью со своими друзьями в социальных сетях.

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

Пока :-)

Как получить IP через PHP для сервера и пользователя

php-uznat-ip-adresДоброго времени суток :-)

На практике часто возникает необходимость узнать IP в PHP скрипте сайта. Причём, это может быть как IP адрес сервера, так и посетителя, производящего действия на вашем ресурсе.

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

Но, к счастью, в PHP получить IP адрес как клиента, так и самого сайта в этом случае более, чем реально. Причём, для этого не потребуются никакие специальные библиотеки и средства движков сайтов. Всё необходимое уже есть в самом PHP «на борту».

Нам осталось только пользоваться :-)

Как в PHP узнать IP сервера

Вся необходимая информация об IP сервера, да и пользователя тоже, в PHP доступна через суперглобальный массив $_SERVER. Однако, помимо перечисленных данных он содержит ещё много различной информации.

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

В частности, для того, чтобы в PHP определить IP адрес сервера, в коде нужно прописать следующую конструкцию:

<?php
    echo $_SERVER['SERVER_ADDR'];
?>

Данный PHP код позволит вам вывести на экран IP адрес сервера, на котором он запускается. Это же значение будет и IP адресом сайта, если он вам где-нибудь понадобится.

Как в PHP получить IP посетителя

Для определения в PHP IP пользователя, с которого он подключается к вашему сайту, мы воспользуемся тем же массивом $_SERVER. В данном случае нас будет интересовать переменная REMOTE_ADDR, содержимое которой можно вывести на экран привычным способом:

<?php
    echo $_SERVER['REMOTE_ADDR'];
?>

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

Чтобы узнать в PHP IP адрес посетителя в данном случае, нужно воспользоваться другим способом.

Как в PHP определить IP пользователя, использующего прокси

Первым делом, в PHP IP посетителя при использовании прокси можно попробовать получить следующим способом:

<?php
    echo $_SERVER['HTTP_CLIENT_IP'];
?>

Данный код можно найти практически во всех PHP скриптах, определяющих реальный IP посетителя. Однако, мало кто может объяснить, что хранится в данной переменной.

Если прописать данный код у себя в сайте на локальном сервере, то вы вообще получите пустое значение, т.е. данной переменной в массиве $_SERVER у вас не окажется. И это не удивительно, т.к. в HTTP_CLIENT_IP хранится глобальный IP пользователя, т.е. его адрес в сети Интернет.

И, самое главное, что на это значение не влияет прокси соединение, т.е. здесь вы найдёте реальный IP пользователя, а не его прокси сервера.

Если по каким-то причинам данная переменная будет отсутствовать в PHP $_SERVER, то можете попробовать узнать IP адрес клиента ещё и таким способом:

<?php
    echo $_SERVER['HTTP_X_FORWARDED_FOR'];
?>

В данную переменную прокси сервера сами помещают реальный IP посетителя.

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

<?php

$client  = @$_SERVER['HTTP_CLIENT_IP'];
$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote  = @$_SERVER['REMOTE_ADDR'];

if(filter_var($client, FILTER_VALIDATE_IP)) $ip = $client;
elseif(filter_var($forward, FILTER_VALIDATE_IP)) $ip = $forward;
else $ip = $remote;

echo $ip;

?>

Данный скрипт выведет на экран значение переменной $ip, в которую при использовании прокси соединения будет записан глобальный IP посетителя. Если же его не будет найдено в PHP $_SERVER, то скрипт попытается узнать IP пользователя, записанный самим прокси сервером.

Если же ни одной переменной не будет присвоено значение, то с большой вероятностью можно предположить, что посетитель не использует прокси либо прокси сервер не предоставляет реальный IP посетителя. В этом случае, чтобы получить хоть какое-то значение IP, мы берём его из REMOTE_ADDR. Но, с высокой долей вероятности, это значение будет IP адресом прокси сервера (благо, что ими не пользуется абсолютно каждый клиент сайтов).

Для проверки существования значений переменных я, как видите, решил воспользоваться PHP функцией filter_var, которая фильтрует переменные с применением определённого фильтра (шаблона), которым в данном случае является FILTER_VALIDATE_IP.

В завершение хочу подытожить, что описанным выше способом, несмотря на все тщательные проверки всех возможных серверных переменных PHP, определить IP пользователя с использованием прокси всё равно не получится на 100%.

Дело в том, что IP адрес клиента предоставляют только определённый тип прокси серверов, которые называют «прозрачными». Как правило, это открытые службы.

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

Оставляйте свои отзывы в комментариях — что понравилось, что нет, может быть, о чём-то следовало бы рассказать поподробнее… Мне интересно любое ваше мнение.

До новых встреч :-)

WordPress капча: мой опыт использования

wordpress-kapchaВсем привет! :-)

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

Сейчас вы, наверное, удивитесь, но всё это было вступление к сегодняшней статье :-)

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

В результате появились предыдущие 4 статьи. Вот так иногда бывает :-)

Статья не будет посвящена обзору всех существующих плагинов капчи, которые можно найти на просторах Интернета по запросу «WordPress капча». Вместо этого я поделюсь с вами отзывами лишь о тех решениях, с которыми я сталкивался на практике лично, и у меня была возможность самостоятельно оценить их плюсы и минусы.

О чём речь пойдёт в статье, думаю, вам понятно. Следовательно, она будет полезна всем, кто заботится о безопасности WordPress сайтов: как разработчикам, так и владельцам ресурсов, кто хочет установить капчу для WordPress самостоятельно.

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

Так что установка капчи на WordPress сайт — обязательная и первостепенная мера, для произведения которой нужно от силы минут 10: 5 на чтение данной статьи, 3 на выбор нужного решения и 2 на его установку :-)

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

Летс гоу :-)

Зачем мне понадобилась WP капча

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

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

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

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

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

Во второй раз о необходимости установки WordPress CAPTCHA я задумался, когда меня стали заваливать спамом в комментариях. Полностью закрывать комментарии для всех пользователей выглядит совсем дико и попахивает тоталитарным режимом :-) Поэтому я решил искать альтернативы.

Первой стала установка стороннего модуля комментариев с помощью виджета ВКонтакте. Думаю, многие видели его на сайтах и ту чушь, которая подчас там содержится.

Всё из-за того, что, в отличие от стандартных комментариев WordPress, при установке сторонних виджетов нет никакой возможности модерирования: что клиент написал, то на твоём сайте и появится.

Такое положение дел меня тоже не устраивало, поэтому я и решил вернуться к использованию механизма WordPress для добавления комментариев, защитив его от спамеров с помощью CAPTCHA, как самого простого и эффективного средства в данной ситуации.

Однако, если с простотой использования мало кто поспорит благодаря массе готовых плагинов WordPress капчи, то с эффективностью, как показала практика, имеются проблемы, о которых я далее и поведаю.

Установка графической капчи для WordPress

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

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

Мой выбор пал на WordPress Captcha Code, который можно скачать в официальном каталоге плагинов ВордПресс по следующему адресу — https://wordpress.org/plugins/captcha-code-authentication/

Я обратил своё внимание на данное решение, т.к. оно было максимально простым и имело по-минимуму разнообразных настроек.

nastrojki-plagina-graficheskoj-kapchi-dlya-wordpress

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

Выглядит данная графическая WordPress капча на сайте следующим образом:

graficheckaya-wordpress-captcha-v-forme-kommentariev

Однако, как выяснилось позже, лаконичность настроек — это как плюс, так и минус, т.к. маленькие баги в вёрстке самого элемента капчи в HTML форм сайта пришлось править вручную. Например, красную звёздочку обязательности ввода значения поля WP CAPTCHA пришлось руками перемещать на одну строку с надписью «Код безопасности» в коде плагина.

Но, самый главный минус данного решения проявился немного позже.

Спустя всего неделю после установки WordPress CAPTCHA Code на свой сайт я обнаружил, что данный плагин не справляется со своими задачами. Поток спама, правда, превратился в ручеёк, но он всё же был.

Видимо, за время, пока ресурс не был защищён с помощью капчи от спама, он уже успел попасть в базы спам ботов, которые продолжали его атаковать и после установки WordPress CAPTCHA. Но в этом был и положительный момент, т.к. данный факт показал несостоятельность плагина WordPress CAPTCHA Code в борьбе со спамом.

Как известно, программисты — народ ленивый :-) И поэтому я уже был готов оставить всё как есть.

В принципе, сократившееся количество спама меня тоже устраивало, а на поиски нового плагина нужно было бы тратить своё драгоценное время, и то ещё не факт, что новый справлялся бы лучше старого. Однако, меня всё-таки заставило отказаться от WordPress CAPTCHA Code одно жирное «НО».

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

Так вот, после его установки выяснилось, что иногда моя графическая WordPress капча была вообще без символов. Т.е. один фон — и всё. При этом от пользователя требовалось ввести невидимые символы, без чего его комментарий не засчитывался. Но и после неправильного ввода при повторной генерации капчи символы не появлялись.

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

Поначалу моя реакция на это явление была предсказуема :-)

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

Но, в один прекрасный день, о данном баге мне написал один из пользователей. И вот в этот момент у меня внутри что-то ёкнуло… Мне стало настолько неудобно, что я решил всё-таки положить край творящемуся беспределу.

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

И это, кстати, касается не только моего сайта, но и других. Уверен, что их владельцам это также будет приятно и необходимо.

Так что, пожалуйста, не будьте равнодушными! Иногда ваши 2-3 слова становятся мощнейшим катализатором, помогающим принимать порой судьбоносные решения, на которые вебмастера не могут решиться самостоятельно годами. Задумайтесь над этим, пожалуйста.

Итак, я прервался на том, что решил поменять плагин ВордПресс капчи. Оставалось только выбрать подходящий.

Установка плагина WordPress reCAPTCHA от Google

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

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

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

В итоге, на том же форуме я нашёл и решение всех бед.

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

Примером такой капчи является популярная Google reCAPTCHA v2, которая называется noCAPTCHA. Самым известным плагином, работающим на её базе, является Google Captcha (reCAPTCHA) by BestWebSoft, которым я и решил воспользоваться для ускоренной интеграции WP капчи на сайт, не вдаваясь в подробности её работы.

Сразу скажу, что поначалу плагин меня порадовал своей полнотой настроек, которые при этом понятны и не избыточны. Кроме того, возле каждого пункта настроек WP капчи есть комментарии по поводу его назначения и скриншоты форм сайта, на которые плагин может быть добавлен:

recaptcha-google-wordpress-nastrojki-plagina

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

Помимо того, что вы видите на картинке выше, есть ещё следующие возможности:

  1. выбор группы пользователей (Администраторы, Редакторы, Авторы и т.д.), для которых капча не будет отображаться;
  2. возможность составления «белого списка» IP адресов, при заходе с которых пользователи смогут совершать действие без ввода капчи;
  3. изменения текста сообщения для посетителей из «белого списка»;
  4. выбор цветовой темы оформления (есть светлая и тёмная);
  5. возможность установки Google reCAPTCHA v1, которая, если кто-то ещё помнит, была обычной графической капчей;
  6. задание собственных стилей оформления с помощью CSS и пользовательского PHP кода.

Устанавливать Google капчу с помощью данного плагина можно, как вы видите, на стандартные формы WordPress, перечисленные в настройках. Также можно установить её и в другие места сайта, в том числе и интегрировать её в другие плагины (например, в Contact Form 7, которую очень любят использовать для форма обратной связи).

Но в последнем случае вам нужно будет разбираться в коде или приобрести Premium версию плагина Google Captcha (reCAPTCHA) by BestWebSoft, в которой есть возможность интеграции в различные плагины путём проставления галочки на странице настроек.

В итоге, на моём сайте в форме комментариев WordPress reCAPTCHA, сгенерированная данным плагином, выглядела следующим образом:

wordpress-google-captcha-v-forme-kommentariev

Что я в итоге могу сказать про данный плагин? В дизайн сайта WordPress Google CAPTCHA noCAPTCHA вписалась идеально. А, самое главное, что со своими функциями — защитой WordPress от спама — данный плагин справлялся идеально.

После его установки прекратился даже тот ручеёк, который оставался после графической капчи от WordPress CAPTCHA Code. Ну и, что немаловажно, Google Captcha (reCAPTCHA) by BestWebSoft решил проблему, создаваемую предыдущим плагином.

Благодаря тому, что Google reCAPTCHA noCAPTCHA — это JavaScript AJAX капча, то серверное кэширование никак не влияло на её работу, позволяя пользователям проходить её каждый раз, как они это пожелают сделать, а не только в тех случаях, когда сгенерированная картинка отображалась на экране.

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

Резюмируя всё вышесказанное, мой отзыв о Google Captcha (reCAPTCHA) by BestWebSoft положительный. Но, несмотря на это, я всё же отказался от данного варианта капчи на своём блоге. Почему — читайте далее.

Установка WordPress reCAPTCHA без плагина

На самом деле, всему виной девушки :-) А в сложившейся ситуации — моя вторая половинка, которая является создателем и автором проекта 50 килограммов счастья, к разработке и поддержке которого я имею непосредственное отношение.

Ну, и, естественно, на данном сайте присутствуют практически все фишки, наработки и плагины, которые я протестировал при создании своего собственного. В том числе, на нём капча до недавнего времени была реализована с помощью Google Captcha (reCAPTCHA) by BestWebSoft.

Но, ввиду особенностей вёрстки шаблона её сайта у неё в форме комментариев на мобильных устройствах WordPress Google CAPTCHA noCAPTCHA, установленная с помощью вышеописанного плагина, стала вылезать за пределы экрана, мешая реальным пользователям её проходить.

Вёрстку менять было нельзя (девушки — народ капризный :-) ), поэтому было принято решение изменить вид самой Google reCAPTCHA.

Сам Google предоставляет два вида reCAPTCHA noCAPTCHA — стандартный, который вы видели выше, и компактный, который предназначен как раз-таки для мобильных устройств. В данном случае Google капча будет выглядеть следующим образом:

wordpress-recaptcha-kompaktnyj-vid

Реализуется это прописыванием одного-единственного параметра в клиентском HTML коде noCAPTCHA, добавляемом на сайт. Но, к сожалению, в Google Captcha (reCAPTCHA) by BestWebSoft данная опция доступна только в премиум версии плагина.

Платить за это маленькое новшество я, естественно, не захотел, поэтому сперва решил дополнить плагин данной фичей самостоятельно. Но, к сожалению, вставка пользовательского кода Google reCAPTCHA в HTML сайта в нём была реализована слишком запутанно, поэтому я принял решение интегрировать noCAPTCHA на сайт самостоятельно с помощью API Google.

О том, как установить Google reCAPTCHA на сайт, я уже писал в статье по ссылке. Изложенные там рекомендации универсальные, а, поскольку у WordPress есть своё API, позволяющая производить многие действия быстрее и красивее с помощью специальных функций, то я решил воспользоваться данной возможностью.

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

Итак, аккаунт вы создали, теперь самое время разместить Google reCAPTCHA на своём WordPress сайте. Напоминаю, что получить ключ reCAPTCHA и подробные инструкции по установке капчи на сайт можно получить на этой странице — https://www.google.com/recaptcha/admin.

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

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

В моём случае WordPress reCAPTCHA располагается на форме комментариев. Её код можно было бы вставить в файл комментариев вручную, но, поскольку я решил воспользоваться API WordPress, то весь мой код будет расположен в файле темы functions.php.

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

Открываем functions.php и пишем следующий код:

function recaptcha_field($fields) {
    global $user_ID;

    if (!$user_ID || ($user_ID && !is_super_admin($user_ID))) {
        $fields['recaptcha'] = '<div class="g-recaptcha" data-size="normal" data-sitekey="ваш_ключ_recaptcha"></div>';
    }
    
    return $fields;
}

add_filter('comment_form_default_fields', 'recaptcha_field');

Как видите, для размещения HTML кода капчи на форме комментариев я решил использовать WP функцию add_filter() с хуком comment_form_default_fields.

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

Данный механизм, кстати, очень популярен при разработке сторонних решений и используется во многих платформах. Например, аналогом WordPress hooks являются Laravel Middleware, о которых я упоминал при знакомстве вас с этим замечательным PHP фреймворком.

В качестве входных параметров add_filter() я передал имя хука и название мое пользовательской функции, в которой будет прописан вывод WordPress reCAPTCHA на экран. В моём случае она называется recaptcha_field, вы же можете придумать что-то пооригинальнее :-)

У хука есть параметр $fields, который соответствует набору полей формы комментирования. В него же мы будем добавлять и нашу капчу в recaptcha_field(), возвращая видоизменённый набор полей.

Также, как вы могли заметить, я установил в теле функции проверку прав текущего пользователя. Если мы залогинены под учёткой главного администратора, то капча нам показываться не будет. Во всех остальных случаях (в том числе и для неавторизованных пользователей) ВордПресс reCAPTCHA будет присутствовать на форме комментариев перед полем для ввода текста.

Сохраняем изменения в functions.php и открываем любую страницу, на которой есть форма добавления комментариев (не забудьте, что нужно быть незалогиненным на сайте).

Если капча не появилась, то не забудьте почистить кэш браузера и проверьте, не забыли ли вы подключить Google reCAPTCHA API на своём сайте. Делается это путём размещения следующей строки перед закрывающимся тэгом или :

<script src='https://www.google.com/recaptcha/api.js'></script>

Если всё сделали верно, а капчи всё так же нет — пишите в комментариях по статьёй, разберёмся вместе 😉

Кстати, если вы хотите установить WordPress reCAPTCHA на другие стандартные формы WordPress (авторизации, восстановления пароля и т.д.), то можно воспользоваться той же WordPress функцией add_filter с другими значениями хуков. Полный их список вы можете найти здесь — https://developer.wordpress.org/reference/hooks/

Если же вам нужно интегрировать WP рекапчу на формы, создаваемые другими плагинами (тот же Contact Form 7), то для этих целей лучше воспользоваться не хуками (если у плагина не будет, конечно, собственного пользовательского хука), а шорткодами.

Для этого достаточно прописать свой шорткод с помощью add_shortcode(). Если это — ваш вариант, то удалите описанный выше код из functions.php и вставьте вместо него следующий:

function recaptcha_html($atts, $content)
{
    global $user_ID;

    if (!$user_ID || ($user_ID && !is_super_admin($user_ID))) {
        $content .= '<div class="g-recaptcha" data-size="normal" data-sitekey="ваш_ключ_recaptcha"></div>';
    }
    
    return $content;
}

add_shortcode('recaptcha_field' , 'recaptcha_html');

Принцип работы данного кода, как видите, такой же, только оформлен он в виде шорткода [recaptcha_field], с помощью которого WordPress reCAPTCHA можно использовать внутри любого текста. Для демонстрации можете разместить его на какой-то текстовой странице и полюбоваться результатами :-)

Итак, код WP капчи в HTML сайта мы добавили. Теперь осталось прописать код проверки правильности её ввода. Для этого у Google так же есть рекомендации, с учётом которых получился следующий код, который также нужно разместить в functions.php после прописанного ранее:

function verify_recaptcha() {
    if (isset($_POST['g-recaptcha-response'])) {
        $captcha_response = $_POST['g-recaptcha-response'];
    } else {
        return false;
    }
    
    $response = wp_remote_post(
            'https://www.google.com/recaptcha/api/siteverify', array(
        'body' => array(
            'secret' => 'ваш_ключ_recaptcha',
            'response' => $captcha_response,
            'remoteip' => $_SERVER['REMOTE_ADDR']
        )
            )
    );
    
    $success = false;

    if ($response && is_array($response)) {
        $decoded_response = json_decode($response['body']);
        $success = $decoded_response->success;
    }
    
    return $success;
}

add_action('preprocess_comment', "precomment_function");

function precomment_function($commentdata) {
    global $user_ID;
    
    if ($user_ID && is_super_admin($user_ID)) {
        return $commentdata;
    }
    if (!verify_recaptcha()) {
        echo '<html>
<head>
<meta charset="UTF-8"><link rel="stylesheet" href="' . get_template_directory_uri() . '/recaptcha_error.css" type="text/css" >
</head>
<body>
<div>
Вы не прошли защиту от спама Google reCAPTCHA. Вернитесь на <a href="#" onclick="history.go(-1);">предыдущую страницу</a> и повторите попытку.
</div>
</body>
</html>';
        exit;
    }

    return $commentdata;
}

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

Смысл изложенного выше кода заключается в том, что мы снова вмешиваемся в процессы WordPress. На этот раз вносим коррективы в добавление нового комментария в БД с помощью add_action(), который имеет такой же смысл и параметры, как и add_filter(), только предназначен для действий, а не для обработки данных.

В качестве хука мы используем preprocess_comment, а функция для описания самого действия носит название precomment_function.

В её теле сперва происходит такая же проверка, как и при отображении нашей WP капчи в HTML, т.е. проверять ввод CAPTCHA мы будем только для тех пользователей, которым она показалась.

Ну, а дальше происходит сама проверка правильности ввода с помощью функции verify_recaptcha(), содержимое которой точь-в-точь, как в статье об установке reCAPTCHA на сайт, о которой я уже упоминал ранее и оставлял на неё ссылку.

Единственное, что я решил модернизировать, так это сама отправка POST запроса на сервер Google, которую я решил реализовать с помощью WordPress функции wp_remote_post(), а не PHP curl_exec() с указанием кучи заголовков.

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

Ну, а CSS стили оформления сообщения я вынес в отдельный файл, который назвал recaptcha_error.css и разместил в директории моей текущей темы на сервере, для чего при вызове файла использовал get_template_directory_uri(). Вы можете разместить его в любом другом удобном для вас месте, не забудьте только url поменять.

Сообщение я решил оформить в стиле экрана авторизации WordPress, для чего использовал следующие стили:

body {
    background:#f1f1f1;
    min-width:0;
    font-family:"Open Sans",sans-serif;
    line-height:1.5;
}
body div {
    width:350px;
    padding:24px 26px;
    margin:40px auto;
    color:#777;
    font-size:14px;
    background:#fff;
    box-shadow:0 1px 3px rgba(0,0,0,.13);
}
@media screen and (max-width: 400px) { 
    body div {
        width:300px;
        font-size:12px
    }
}

Ну вот и всё. Капча для WordPress готова. Осталось только протестировать :-)

Если капчу не ввести или как-то умудриться сделать это неверно, то на экране мы увидим следующее сообщение:

oshibka-prokhozhdeniya-kapchi-dlya-wordpress

Если же всё прошло успешно, то комментарий появится в админке сайта:

kommentarij-dobavlennyj-posle-vvoda-wordpress-google-captcha

И на этой позитивной ноте я уже было хотел попрощаться с вами, но неожиданно вспомнил то, из-за чего весь этот сыр-бор с самописной WordPress капчей вообще затеялся. А именно, из-за того, что я не не знал как сделать компактную Goggle reCAPTCHA на WordPress.

Так вот. Для того, чтобы придать ей мобильный вид необходимо в HTML коде капчи изменить значение параметра data-size с normal на compact. Ну, а поскольку изначально проблемы с размером ВордПресс reCAPTCHA у моей девушки на сайте наблюдались только в мобильной версии, то я видоизменил строку добавления капчи на форму комментариев следующим образом:

$fields['recaptcha'] = '<div class="g-recaptcha" data-size=' . (wp_is_mobile() ? "compact" : "normal") . ' data-sitekey="ваш_ключ_recaptcha"></div>';

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

vordpress-kapcha-v-kommentariyakh-na-mobilnykh-ustrojstvakh

Для этого мне нужно было узнать какой-то идентификатор капчи (класс или id), который присваивался HTML элементу самим Google. Таковым оказался класс .g-recaptcha, которому я и задал необходимые стили. А, поскольку проблема с размером WordPress reCAPTCHA у меня наблюдалась только на экранах мобильных устройств шириной менее 420px, то итоговый CSS код, добавленный в style.css моей темы вышел таким:

@media screen and (max-width:420px) {
    .g-recaptcha {
        transform:scale(0.96);
        -webkit-transform:scale(0.96);
        transform-origin:0 0;
        -webkit-transform-origin:0 0;
    }
}

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

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

kapcha-v-kommentariyakh-wordpress-itogovyj-variant

На этом наша самостоятельная установка reCAPTCHA на WordPress сайт без плагина закончена.

И на данный момент последний описанный вариант реализации WordPress CAPTCHA является текущим для данного сайта, на котором я решил остановиться.

Понимаю, что он неидеален, т.к. требует от пользователей много телодвижений и, порой, специальных знаний, при установке на сайт, но зато гибкий и позволяет производить с капчей различные преобразования с помощью параметров, описанных в официальной документации Google reCAPTCHA — https://developers.google.com/recaptcha/docs/display#config

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

И жду от вас лайков и репостов в соцсетях, если сегодняшняя статья не оставила вас равнодушными.

На этом у меня всё. До новых встреч! :-)

Делаем капчу на PHP: установка reCAPTCHA и код с нуля

kak-cdelat-kapchu-na-phpВсем привет! :-)

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

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

Поэтому сегодняшняя статья будет состоять из двух частей: установка reCAPTCHA от Google и того, как сделать капчу на PHP самостоятельно.

Указанные в статье примеры будут универсальные, без привязки к какой-либо платформе сайта, поэтому их можно использовать абсолютно на любом сайте, разработанном с использованием PHP и HTML.

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

Если вы — опытный разработчик, то следующий абзац смело пропускайте.

Как работает капча

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

Механизм работы HTML форм следующий:

  • пользователь вводит информацию в соответствующие поля;
  • нажимает на кнопку «Отправить» или с похожим названием, оформленную в виде HTML элемента input type=»submit»;
  • при этом данные формы отправляются на сервер, где происходят дальнейшие действия. Имя серверного скрипта прописано в атрибуте action HTML-тэга form.

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

Затем на сервере проверяется значение капчи с правильным ответом и если они совпадают, то действие, производимое пользователем с помощью формы, выполняется.

Если же нет — выдаётся сообщение о неправильном вводе капчи, а иногда ещё и происходит фиксация IP-адреса, с которого была произведена попытка ввода неверной CAPTCHA, с дальнейшим внесением его в blacklist и блокированием доступа как к сайту в целом, так и к отдельным элементам.

На таком принципе была основана работа самых первых, так сказать, «классических» капч, и он до сих пор успешно применяется.

Разнообразие в данный механизм вносят JS капчи, которые отправляют AJAX запрос на сервер для проверки правильности ввода в режиме «реального времени», т.е. без перезагрузки страницы. Ярким представителем JavaScript капчи является всем известная Google reCAPTCHA noCAPTCHA, об установке которой мы поговорим далее.

Итак, как работает капча, мы разобрались. Из её принципа работы следует, что сама реализации капчи CAPTCHA будет содержать клиентский код (HTML элемента капчи) и серверный (PHP скрипт, обрабатывающий ответ пользователя).

В случае использования сторонних решений вам, скорее всего, понадобится только клиентский код. Серверный может быть ограничен только лишь отправкой запросов на сторонний сервер для проверки правильности ввода (у той же самой Google reCAPTCHA v2).

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

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

Теперь самое время перейти от сухой теории к практическому применению полученных знаний и сделать капчу на PHP самостоятельно.

Как сделать капчу на PHP — подготовка формы

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

Она будет состоять из поля для ввода текста и кнопки «Отправить», между которыми в будущем мы будем размещать нашу капчу.

Код формы следующий:

<html lang="ru">
    <head>
        <title>CAPTCHA demo</title>
        <meta charset="utf-8">
		<script src='https://www.google.com/recaptcha/api.js'></script>
    </head>

    <body>
        <form method="post" action="verify_captcha.php">
            <p>
                <b>Введите комментарий:</b>
            </p>

            <p>
                <textarea name="comment" rows="12" cols="21"></textarea>
            </p>
			
            <p>
                <input type="submit" value="Отправить">
            </p>
        </form>
    </body>
</html>

Внешне она выглядит следующим образом:

delaem-kapchu-na-forme-kommentariev

Для удобства разработки и демонстрации результатов я решил создать новый репозиторий на Github, в котором можно будет найти весь код, приведённый в данной статье.

Для каждой реализации капчи создан отдельный каталог с идентичной структурой.

Поскольку наша форма комментариев на момент разработки является самостоятельным решением, а не частью существующей страницы сайта, то для её запуска в каждом каталоге есть файл index.php. В нём же происходит вызов файла form.html, содержащего описанный выше код.

Данная структура приложения была выбрана не случайно, т.к. она максимально соответствует реальным проектам, в которых html вызывается из PHP скрипта на сервере. Поэтому для интеграции кода капчи из статьи на свой сайт всё, что вам потребуется, — это скопировать form.html к себе на сервер, а код из index.php в свой серверный скрипт, вызывающий необходимую форму.

Или перенести содержимое вышеуказанных файлов в соответствующие.

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

Серверные скрипты были разработаны на PHP 5.6, но и на более поздних версиях (PHP 7+) с ними проблем не будет, т.к. я старался не использовать deprecated конструкции.

Установка reCAPTCHA

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

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

Для того, чтобы получить ключ reCAPTCHA, нужно создать Google-аккаунт, который даёт доступ ко всем сервисам данной компании (Youtube, Google диск, почта Gmail и др.) либо воспользоваться существующим (думаю, у большинства из вас он есть, если вы пользуетесь хотя бы одним из перечисленный сервисов).

После того, как вы залогинитесь в своём аккаунте, переходим на страницу https://www.google.com/recaptcha/admin, вводим название капчи (можно добавлять несколько CAPTCHA, поэтому имя нужно для банальной идентификации) и выбираем нужную версию reCAPTCHA.

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

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

ustanovka-recaptcha-nocaptcha-ot-google

Нажимаем на кнопку «Регистрация» и попадаем на страницу управления созданной капчей с доступом к статистике её ввода, кодом reCAPTCHA и списком инструкций по установке reCAPTCHA на сайт.

Просто выполняем описанные шаги:

kod-recaptcha-ot-google

Добавление кода reCAPTCHA в виде поля на HTML форму описано достаточно подробно, поэтому не буду его ещё раз повторять. Просто выполните указанные выше инструкции.

В результате наша форма должна принять следующий вид:

delaem-kapchu-ustanovka-recaptcha

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

Итак, HTML часть капчи завершена, настало время для серверной реализации. Как заметно из инструкции от Google, серверная проверка ввода капчи происходит следующим образом: после решения капчи пользователем результат отправляется на локальный сервер в виде значения параметра g-recaptcha-response.

Затем на локальном сервере нужно отправить POST-запрос на сервер reCAPTCHA, который уже и возвращает итоговый ответ: правильно ли была введена капча пользователем или он оказался роботом и не смог пройти все линии защиты.

Подробного примера реализации, как при установке reCAPTCHA на HTML форму, здесь у Google нет, т.к. неизвестно на каком языке написаны ваши серверные скрипты, а предоставлять примеры для всех существующих ныне серверных языков — это утомительно и долго, т.к. их около 20.

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

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

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

Для отправки запроса на сервер Google для проверки правильности ввода PHP капчи был создан отдельный скрипт verify_captcha.php со следующим кодом:

<?php

if (isset($_POST['g-recaptcha-response'])) $captcha_response = $_POST['g-recaptcha-response'];
else die('На форме нет капчи! Обратитесь к администратору!');

$url = 'https://www.google.com/recaptcha/api/siteverify';
$params = [
    'secret' => 'ваш_секретный_код_google',
    'response' => $captcha_response,
    'remoteip' => $_SERVER['REMOTE_ADDR']
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($ch);
if(!empty($response)) $decoded_response = json_decode($response);

$success = false;

if ($decoded_response && $decoded_response->success)
{
    $success = $decoded_response->success;
}

$result = $success ? 'Капча пройдена успешно!' : 'Неверная капча!';
echo $result;

Немного комментариев.

Сперва в коде идёт проверка наличия параметра g-recaptcha-response в запросе, отправленном при подтверждении формы. Если же параметра нет, что равноценно отсутствию reCAPTCHA на форме, то скрипт завершает свою работу с соответствующим сообщением.

Далее мы отправляем POST запрос средствами PHP на сервер reCAPTCHA, как это требует Google, и анализируем полученный ответ, предварительно преобразовав его из JSON-формата в обычный объект.

Если ответ от сервера содержит параметр success со значением true, то всё прошло успешно. В противном случае ответ будет содержать параметр errors с указанием причины неудачного действия.

В итоге скрипт после завершения своей работы выводит на экран итоговое сообщение с текстом «Капча пройдена успешно!» в случае успешного выполнения серверного сценария и «Неверная капча!», если в процессе произошли какие-то ошибки.

При использовании приведённого примера интеграции Google reCAPTCHA в реальном проекте вместо сообщений должны быть прописаны необходимые действия.

Делаем капчу своими руками

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

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

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

Поэтому созданием самописок уже давно никто не занимается.

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

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

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

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

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

В силу приведённых причин я и решил «изобрести очередной велосипед» для реализации графической капчи, кодом которого с вами и хочу поделиться. Он доступен в репозитории данного урока в каталоге image_captcha.

Вообще-то, слово «изобрести» в моём случае тоже не совсем подходит, т.к. за основу я взял существующую реализацию с Хабра — https://habrahabr.ru/post/120615/, структурировав её код, убрав некоторые ошибки, переделав непонравившиеся мне моменты и добавив свои наработки.

Так что далее в статье и в репозитории на github вы найдёте плоды коллективного труда и можете поучаствовать в его доработке и развитии сами, если сочтёте нужным.

HTML код элемента CAPTCHA для интеграции капчи на форму будет следующий:

<p>
    <img src='/captcha.php' id='captcha-image'>

    <a href="javascript:void(0);" onclick="document.getElementById('captcha-image').src = 'captcha.php';">
        Обновить капчу
    </a>
</p>

Его нужно добавить в нужное место вашей HTML формы на сайте. В моём примере он будет располагаться после textarea name=»comment».

В файле captcha.php, мы будем создавать капчу, а на выходе выдавать изображение без сохранения его на диск. Во-первых, это сэкономит ресурсы сервера, а во-вторых, сократит время генерации капчи, что на больших проектах будет заметно.

Сперва я прописал генерацию символьной последовательности и самой картинки сплошным кодом, но потом решил его немного структурировать путём создания класса CaptchaValue с соответствующими методами. В итоге, captcha.php принял следующий вид:

<?php

include('classes' . DIRECTORY_SEPARATOR . 'CaptchaValue.php');

$captcha = new CaptchaValue();
$captcha_code = $captcha->generate_code();
$captcha->captcha_image($captcha_code);

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

<?php

interface CaptchaInterface
{
	public function session_write($code);
	public function generate_code();
}

Файлы классов и интерфейса я вынес в отдельный каталог ‘classes’, который размещён на уровень ниже form.html и других файлов, расположенных в корне, поэтому либо сделайте как я, либо исправьте пути к файлам классов везде, где они подключаются в коде через PHP директиву include.

Сам класс CaptchaValue, код которого расположен в CaptchaValue.php, выглядит так:

<?php

include('CaptchaInterface.php');

class CaptchaValue implements CaptchaInterface
{
    private $font_dir = '';

    public function __construct()
    {
        $this->font_dir = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'fonts' . DIRECTORY_SEPARATOR;
    }

    public function session_write($code)
    {
        session_start();
        
        $_SESSION['captcha_value'] = md5(md5($code));
        $_SESSION['answer_time'] = strtotime(date('d-m-Y H:i:s'));
    }

    public function generate_code()
    {
        $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
        $length = rand(4, 6);
        $numChars = strlen($chars);

        $str = '';
        for ($i = 0; $i < $length; $i++)
        {
            $str .= substr($chars, rand(1, $numChars) - 1, 1);
        }

        $array_mix = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
        srand((float) microtime() * 1000000);
        shuffle($array_mix);

        $result = implode("", $array_mix);
        $this->session_write($result);

        return $result;
    }

    public function captcha_image($code)
    {
        $image = imagecreatetruecolor(150, 70);
        imagesetthickness($image, 2);

        $background_color = imagecolorallocate($image, rand(220, 255), rand(220, 255), rand(220, 255));
        imagefill($image, 0, 0, $background_color);

        $linenum = rand(3, 5);
        for ($i = 0; $i < $linenum; $i++)
        {
            $color = imagecolorallocate($image, rand(0, 150), rand(0, 100), rand(0, 150));
            imageline($image, rand(0, 150), rand(1, 70), rand(20, 150), rand(1, 70), $color);
        }

        $font_arr = array_values(array_diff(scandir($this->font_dir), array('.', '..')));
        $font_size = rand(20, 30);
        $x = rand(0, 10);

        for ($i = 0; $i < strlen($code); $i++)
        {
            $x += 20;
            $letter = substr($code, $i, 1);
            $color = imagecolorallocate($image, rand(0, 200), 0, rand(0, 200));
            $current_font = rand(0, sizeof($font_arr) - 1);

            imagettftext($image, $font_size, rand(-10, 10), $x, rand(50, 55), $color, $this->font_dir . $font_arr[$current_font], $letter);
        }

        $pixels = rand(2000, 4000);
        for ($i = 0; $i < $pixels; $i++)
        {
            $color = imagecolorallocate($image, rand(0, 200), rand(0, 200), rand(0, 200));
            imagesetpixel($image, rand(0, 150), rand(0, 150), $color);
        }

        for ($i = 0; $i < $linenum; $i++)
        {
            $color = imagecolorallocate($image, rand(0, 255), rand(0, 200), rand(0, 255));
            imageline($image, rand(0, 20), rand(1, 50), rand(150, 180), rand(1, 50), $color);
        }

        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s", 10000) . " GMT");
        header("Cache-Control: no-store, no-cache, must-revalidate");
        header("Cache-Control: post-check=0, pre-check=0", false);
        header("Pragma: no-cache");
        header("Content-type: image/png");

        imagepng($image);
        imagedestroy($image);
    }
}

Здесь без комментариев не обойтись, т.к. мы рассматриваем самый главный класс всего приложения.
Расскажу конкретно о каждом методе, начиная с самого главного, в котором происходит вся магия, — captcha_image().

Генерировать изображение капчи на PHP я решил следующим образом:

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

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

За создание объекта изображения отвечает PHP функция imagecreatetruecolor(), которой я в качестве параметров передал размеры генерируемой картинки. В моём случае ширина изображения 150px и высотой 70px.

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

Далее я указал толщину будущих наносимых линий с помощью imagesetthickness(), задав её 2 пикселя.

Для задания фона изображения я использовал PHP функцию imagefill(), в качестве аргумента которой был указан цвет, сгенерированный с помощью imagecolorallocate(). Цвет фона, как вы видите, динамический, т.е. каждый раз задаётся случайно.

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

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

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

Далее идёт посимвольная прорисовка строки $code, которая генерируется функцией generate_code() и передаётся в качестве аргумента в captcha_image().

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

  1. задаём строку символов, из которых будет состоять наша итоговая последовательность;
  2. из неё выбирается случайное количество символов (от 4 до 6 в моём случае);
  3. символы для верности ещё раз перемешиваются;
  4. полученная строка записывается в сессию методом session_write() в переменную $captcha_value, где попутно фиксирует время генерации PHP капчи в переменной $answer_time для дальнейшей проверки времени её ввода пользователем;
  5. функция возвращает итоговую строку символов для дальнейшего использования.

Теперь вернёмся снова в image_captcha() к циклу прорисовки символов случайной строки:

$font_arr = array_values(array_diff(scandir($this->font_dir), array('.', '..')));
$font_size = rand(20, 30);
$x = rand(0, 10);

for ($i = 0; $i < strlen($code); $i++)
{
    $x += 20;
    $letter = substr($code, $i, 1);
    $color = imagecolorallocate($image, rand(0, 200), 0, rand(0, 200));
    $current_font = rand(0, sizeof($font_arr) - 1);

    imagettftext($image, $font_size, rand(-10, 10), $x, rand(50, 55), $color, $this->font_dir . $font_arr[$current_font], $letter);
}

Для прорисовки символов я решил воспользоваться различными шрифтами. Они должны быть в виде ttf файлов, и для них был создан отдельный каталог, путь к которому задаётся в виде private свойства класса CaptchaValue font_dir. Значение его задаётся в конструкторе.

Итак, получаем список файлов из указанной директории с помощью PHP scandir() и записываем результаты в массив $font_arr. В переменной $font_size у нас будет храниться случайно сгенерированное значение размера шрифта, а в $x — случайное значение, которое будет использоваться для вычисления позиции символов нашей строки на изображении.

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

Первая же строка цикла $x += 20; вычисляет положение текущего символа на изображении. Если хотите расположить символы ближе/дальше друг от друга, то изменения стоит вносить в данную строку. Можете даже сделать шаг случайным значением, но тогда есть вероятность, что символы будут попросту перекрывать друг на друга.

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

Наносим символ на изображение с учётом всех полученных до этого данных PHP функцией imagettftext(), которая позволяет делать это с применением ttf шрифтов, что, отражает её название.

О назначении каждого её параметра можете прочитать в официальной документации PHP, я же хочу обратить внимание на третий, которому я указал значение rand(-10, 10).

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

Рассмотрим оставшийся код метода captcha_image().

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

Сперва мы генерируем число точек, которыми будем создавать шум (в моём случае их будет от 2000 до 4000, что для картинки 150х70 в самый раз).

Затем генерируем цвет каждой точки заново (без этого можно обойтись, задав всем одинаковый, например, белый) и наносим её на изображение с помощью стандартной PHP функции imagesetpixel().

После данного преобразования я ещё раз наношу линии уже поверх нарисованных символов описываемым ранее способом: в цикле по количеству линий с помощью функции PHP imageline(). Цвет каждой снова генерируется случайным образом.

Всё, картинка готова.

Осталось только вывести её на экран в окне браузера с помощью PHP функции imagepng(), для чего браузеру передаются соответствующие заголовки с помощью PHP header(), и очистить память сервера от изображения, которое мы генерировали, с помощью PHP imagedestroy().

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

graficheskaya-kapcha-na-php-svoimi-rukami

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

За генерацию отвечает класс CaptchaField, описанный в скрипте classes/CaptchaField.php, а именно его метод generate_code(), который вызывается в главном файле, запускающем всю реализацию как самостоятельный сайт, index.php:

<?php

include('classes' . DIRECTORY_SEPARATOR . 'CaptchaField.php');

$captcha_field = new CaptchaField();
$captcha_code = $captcha_field->generate_code();

include_once('form.html');

Как видите, сгенерированное значение записывается в переменную $captcha_code, которая затем выводится в HTML коде нашей формы комментариев вместо имени поля для ввода капчи:

<p>
    <span>Введите капчу:</span>
    <input type="text" name="<?php echo $captcha_code; ?>">
</p>

Сам класс CaptchaField выглядит следующим образом:

<?php

error_reporting(E_ERROR);

include('CaptchaInterface.php');

class CaptchaField implements CaptchaInterface
{
    public function session_write($code)
    {
        session_start();
        $_SESSION['captcha_field'] = $code;
    }

    public function generate_code()
    {
        $captcha_field = md5(md5(uniqid('', true) . date('His')));
        $this->session_write($captcha_field);

        return $captcha_field;
    }

}

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

Поскольку данный класс реализует интерфейс CaptchaInterface, то должен переопределять его методы generate_code() и session_write().

В данном классе, как и в случае CaptchaValue, они отвечают за генерацию кода и запись его в сессию, соответственно. Только код в данной ситуации у нас другой.

Для генерации имени поля для ввода капчи я решил использовать PHP функцию uniqid для генерации случайного идентификатора. Первый параметр функции пустой, т.к. я решил обойтись без строчного префикса, а второй — true, что добавляет энтропию для увеличения уникальности значения и удлиняя его до 23 символов вместо 13.

Ну, и для большей секьюрности я решил ещё дополнительно применить двойное md5 шифрование. В результате, метод generate_code() класса CaptchaField вернёт следующее значение, предварительно записав его в переменную сессии captcha_field:

graficheskaya-kapcha-na-php-pole-vvoda-captcha

Итак, сама PHP CAPTCHA и сгенерированное имя поля для её ввода готовы.

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

За проверку, как и в случае реализации Google noCAPTCHA reCAPTCHA, которая была приведена выше, отвечает серверный скрипт verify_captcha.php.

Поскольку я решил структурировать данную реализацию путём создания классов, то verify_captcha.php выглядит так:

<?php

include('classes' . DIRECTORY_SEPARATOR . 'CaptchaVerify.php');

$captcha_verify = new CaptchaVerify();
$captcha_verify->verify_code();

Сам же класс CaptchaVerify выглядит следующим образом:

<?php

class CaptchaVerify
{

    private $captcha_value = '';
    private $captcha_field = '';
    private $answer_time = '';

    private function session_read()
    {
        session_start();
        
        $this->captcha_value = $_SESSION['captcha_value'];
        $this->captcha_field = $_SESSION['captcha_field'];
        $this->answer_time = $_SESSION['answer_time'];

        unset($_SESSION['captcha_value']);
        unset($_SESSION['captcha_field']);
        unset($_SESSION['answer_time']);
    }

    private function error_msg($message)
    {
        $_SESSION[$_SERVER['REMOTE_ADDR']] ++;
        exit($message);
    }

    public function verify_code()
    {
        $this->session_read();

        if (isset($_SESSION[$_SERVER['REMOTE_ADDR']]) && $_SESSION[$_SERVER['REMOTE_ADDR']] >= 10)
            $this->error_msg('Вы ввели слишком много неверных капчей! Обратитесь за помощью к администратору admin@admin.net');

        if (isset($_POST['submit_form']) && !empty($this->captcha_value) && !empty($this->captcha_field) && !empty($this->answer_time))
        {
            $this->current_time = strtotime(date('d-m-Y H:i:s'));

            if ($this->current_time - $this->answer_time < 6)
                $this->error_msg('Вы или робот или вводите капчу слишком быстро!');
            if ($_POST[$this->captcha_field] == '')
                $this->error_msg('Робот, уходи!');

            if (md5(md5($_POST[$this->captcha_field])) == $this->captcha_value)
                echo 'Капча пройдена успешно!';
            else
                $this->error_msg('Неверная капча!');
        }
        else $this->error_msg('Хакер, уходи!');
    }
}

Главным его методом является verify_code(), который и вызывается в verify_captcha.php.

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

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

Поэтому в таком случае скрипт завершается с соответствующим сообщением об ошибке «Вы или робот или вводите капчу слишком быстро!». Кстати, данный текст подскажет реальным пользователям, которые вводят PHP CAPTCHA слишком быстро, делать это медленее, чтобы их старания были засчитаны.

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

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

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

Если таковых наберётся больше 10, то выполнения действия невозможно будет даже при правильном вводе капчи. Для разблокировки нужно будет написать администратору, чтобы тот сбросил счётчик.

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

Поэтому на практике используйте вариант с БД. В сессию запись была сделана в качестве демонстрации данной возможности.

Или вообще можете отказаться от данного способа защиты капчи от взлома, если считаете его слишком жёстким. Всё в ваших руках :-)

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

Надеюсь, я ответил на вопрос о том, как сделать капчу на PHP. Причём поделился с вами аж двумя вариантами.

Честно скажу, что реализованная мною графическая капча не является бронебойной и 100% защиту от всех современных способов взлома не предоставляет. Повторюсь, мне была интересная её реализация только с точки зрения практического применения способов защиты от обхода капчи и хотелось вспомнить возможности PHP для работы с изображениями.

Своей цели я достиг. А если ещё и смог быть вам полезным своим трудом — для меня будет вдвойне приятно :-)

Если вы планируете устанавливать капчу на реальный проект, то рекомендую воспользоваться всё-таки готовыми и оттестированными решениями. Той же самой Google reCAPTCHA, порядок установки которой описан в первой части статьи.

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

Поэтому пишите свои отзывы в комментариях под статьёй: что понравилось, что не понравилось, что можно улучшить.

Очень надеюсь на вашу помощь и поддержку.

До новых встреч :-)

Обход капчи: 10 способов

kak-obojti-kapchuВсем привет! :-)

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

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

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

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

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

И в завершение вступления хочу напомнить вам пословицу «Знание — сила» и слова дяди Питера Паркера (больше известного как «Человек-паук») — «Чем больше сила, тем больше ответственность».

Следовательно, чем больше у вас знаний, тем больше должно быть ответственности при их использовании.

Очень надеюсь на ваше понимание и применение приведённой далее информации в благих целях.

Поехали!

Как обойти капчу?

Как выяснилось — не так уж и сложно. Для обхода капчи, как и для других современных киберпреступлений, на данный момент есть целых два пути:

  1. использование особенностей реализации CAPTCHA и их слабые места;
  2. применение современных технологий.

Что касается способов обхода капчи и атак на сайты в целом, то их существует три основных направления:

  • ручной взлом CAPTCHA (хакер изучает конкретную реализацию капчи и подбирает способы её взлома);
  • использование специальных программ (роботов), с помощью которых организовываются массовые автоматизированные атаки на несколько сайтов одновременно (как правило, разработанных на одной платформе или имеющих одинаковые капчи, к которым удалось подобрать «ключи» хакерам);
  • эксплуатация труда реальных людей.

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

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

А потом уже ставятся на поток, т.е. организовываются автоматически с применением программ-роботов (ботов).vvod-kapchi-avtomatom

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

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

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

Для создания интриги скажу, что их на данный момент существует целых три.

Обход капчи из-за ошибок реализации

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

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

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

Как я и обещал, в данном разделе я рассмотрю самые распространённые, а также способы защиты от них. И начнём, как обещалось, с самого примитива.

Обход капчи с фиксированным набором задач

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

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

Т.е. заходим на такой сайт, подбираем ответы, составляем БД из заданий и правильных решений и пишем бота для брутфорс атак, который будет подбирать подходящие варианты.

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

А если такие люди и есть, то они очень быстро учатся на своих ошибках, когда теряют контроль над своим сайтом или клиентов, которых из-за таких творений взламывали.

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

kak-vzlomat-kapchuЕщё одним способом защиты от подобного ввода капчи автоматом является изменения имени поля формы, в которое должен вводиться ответ. Если имя поля, например, всегда будет «captcha», то злоумышленнику будет проще такую капчу взломать. Его программа-робот будет всего лишь отправлять запрос к серверному скрипту, указанному в HTML атрибуте «action» формы, содержащем необходимое значение капчи.

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

Если же имя поля, как и само задание для прохождения капчи будет генерироваться на сервере, то никакая база имён капчи не поможет. Для того, чтобы использовать динамическое название поля, на практике капча генерируется одним скриптом, а обрабатывается другим.

В данном случае реализации капчи имеется один существенный нюанс: скрипту, обрабатывающему правильность её ввода, нужно будет как-то передавать имя поля капчи. Делается это чаще всего с помощью скрытого input формы, data-атрибутов или передаче их через cookies или сессию.

Ключевым моментом является то, что нельзя передавать имя напрямую, т.е поле капчи называется «captcha_mysite», а в hidden поле стоит значение «captcha_mysite» или «site». Оно обязательно должно быть зашифровано, причём расшифровка должна происходить с применением того же алгоритма, что и шифрование.

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

Кстати, достаточно вместо имени поля использовать случайную последовательность символов, которую в языке PHP очень просто получить с помощью функции uniqid().

Обход капчи с помощью сессий

Если реализация капчи подразумевает хранение правильного ответа в сессии, и сессия не создаётся заново после каждого ввода капчи, то злоумышленники могут узнать идентификатор сессии и узнать зашифрованное значение CAPTCHA.

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

Также, если в коде проверки ответа пользователя на сервере программист не выполнит проверку на пустоту переменной сессии, в которой передаётся ответ пользователя, то хакер может использовать несуществующий идентификатор сессии, для которой переменной просто не будет существовать.kak-projti-kapchu

За счёт этого упущения подобные капчи могут быть пройдены с помощью подсовывания несуществующих id сессий и пустых значений капчи.

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

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

Взлом капчи из-за секретной информации в клиентском коде

Иногда капчи делают таким образом, что при передаче пользовательских значений на сервер используют шифрование с использованием так называемой «соли», т.е. добавления к значению CAPTCHA ID сессии, значения IP или других уникальных данных. Нередко таковым может являться простая случайная последовательность символов.

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

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

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

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

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

Также нужно пересоздавать ID сессии и генерировать другие уникальные значения (включая и саму CAPTCHA, если это возможно) после каждой попытки ввода капчи, что убережёт вас или, по крайней мере, усложнит задачу хакерам по взлому сайта путём автоматического подбора правильного значения.

Ещё одно средство защиты — по возможности, блокировать действия по IP и количествам попыток.

Как обойти капчу без изменения IP

Брутфорс атака является эффективным способом обхода капчи не только в случаях реализации её с фиксированным набором заданий и их решений.

obkhod-kapchi-avtomatomЕщё одна ошибка при реализации CAPTCHA, которая делает её уязвимой для автоматизированных атак, это — отсутствие ограничений времени на решение капчи и количество попыток.

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

Защита: при реализации по-настоящему безопасной капчи нужно лимитировать время на ответ и количество попыток решения капчи с одного IP для блокирования брутфорс атак роботов.

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

Если это действительно был человек, то он примет соответствующие меры, а если робот — он продолжит предпринимать попытки обхода капчи.

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

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

Но, по правде говоря, эти меры мало чем помогут благодаря существованию прокси серверов.

Обход капчи с помощью прокси

Даже в ситуациях, когда блокирование большого количества попыток решения капчи по IP всё-таки происходит, 100% защиту от роботов это мероприятие не обеспечивает.

Всему виной прокси сервера и программы анонимайзеры, работающие на их базе, о которых известно, пожалуй, каждому современному школьнику, ищущему способы обхода родительского контроля и блокировки запретных сайтов.kak-izbezhat-kapchu-avtomatom

Анонимайзеры позволяют скрывать данные компьютера при пользовании сайтом, в том числе и заветный IP адрес, по которому клиента можно вычислить и заблокировать.

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

Таким образом, злоумышленник с лёгкостью обойдёт все ваши блокировки по IP и будет подбирать правильное решение капчи столько, сколько ему потребуется.

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

Данный способ использовали ещё полвека назад при написании первых программ с целью прохождения теста Тьюринга, реализацией которого и является CAPTCHA.

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

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

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

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

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

Ввод капчи автоматом с помощью эмуляторов действий

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

kak-obojti-kapchu-avtomatomЕдинственная проблема, которая может стоять в данной ситуации перед хакером — это как найти нужный элемент управления на сайте программно.

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

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

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

Как обойти капчу при помощи высоких технологий

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

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

Итак, как избежать капчу при помощи современных технологий?

Обход капчи с помощью OCR

OCR (Optical Character Recognition — оптическое распознавание символов) — технология для распознавания печатного или машинописного текста для дальнейшего его использования в электронном формате. Наиболее известным ПО, реализующим эту технологию, является Adobe FineReader.

Успешно используется при создании программ автоматического ввода капчи, успешно распознающих и решающих графические капчи, для прохождения которых нужно ввести последовательность символов, изображённых на картинке.kak-izbezhat-kapchu

Хакеры, естественно не пользуются Adobe FineReader (хотя, может, и такие есть :-) ), а пишут специальные скрипты, которые с применением различных готовых библиотек для работы с изображениями либо с использованием возможностей языка для работы с графикой, распознают капчу и выдают символьную последовательность, изображённую на ней.

В Интернете я нашёл достаточное количество примеров таких скриптов. Принцип их работы заключался в следующем:

  • очищение изображения, используемого в графических CAPTCHA, от различных шумов;
  • разбиение изображённой строки на отдельные символы;
  • сравнение каждого из них с заготовленной картинкой (образцом).

Графические образцы подготавливались с учётом различных шрифтов и возможных искажений (наклоны, повороты и т.д.).

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

Защита: собственно говоря, с целью запутывания OCR программ и применяются всех раздражающие шумы и искажения символов на картинках, из-за которых текст иногда сложно разобрать даже человеку. Но, в случае роботов это тоже хорошо работает, в результате чего OCR алгоритмы не могут выдать 100% точный результат, что положительно влияет на безопасность капчи и сайтов, её использующих.

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

  1. Символы на разных CAPTCHA должны иметь различные координаты.
  2. Если вы используете какие-то эффекты шума для создания фона, то его цвет должен совпадать с цветом символов, иначе фон можно легко убрать, выделив символы для распознавания.
  3. Расстояние между символами должно быть минимально. Можно даже накладывать их друг на друга, но только без фанатизма, чтобы реальные пользователи могли их распознать.
  4. Использовать различные шрифты, чтобы было сложно подобрать подходящий для распознавания.
  5. Всячески искажать символы, менять их начертание и толщину.
  6. Использовать специальные библиотеки, позволяющие изменять символы таким образом, что для их программного распознания будет невозможно подобрать шрифт. Примером такого решения является капча от создателя ресурса captcha.ru, при генерации которой используется авторский алгоритм волнообразного искажения символов.

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

Как пройти капчу с помощью нейронных сетей

Если OCR — технология достаточно старая (первые запатентованные устройства известны в начале XX века), то искусственные нейронные сети (ИНС) появились лишь во второй половине предыдущего столетия (для технологий 50 лет — это существенный возраст :-) ).

programmy-dlya-obkhoda-kapchiИменно алгоритмы ИНС лежат в основе искусственного интеллекта (ИИ), целью которого является создание программ и устройств, наделённых творческими функциями, т.е. создание рукотворного человека.

На данный момент ИИ постоянно развивается, и с каждым днём появляются всё новые и изобретения, обладающими не виданными ранее свойствами.

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

С помощью их можно:

  • распознавать объекты на фотографиях (от пола изображённого человека и марки его джинсов до того, какой игре принадлежит анализируемая картинка, со всей её цветовой палитрой, названием локации и того, что на ней происходит);
  • управлять устройствами голосом и жестами;
  • писать аннотации к видео на основании того, что происходит в видеоролике и др.

Естественно, что при данных возможностях создание программы для автоматического ввода капчи с применением принципов ИНС не представляет сложности для знающих людей.

Один из таких продуктов был разработан компанией Vicarious в 2014 году. Разработанная ей нейронная сеть способна распознавать капчу в 90% случаях (напомню, что для решения классического теста Тьюринга, которым и является CAPTCHA, необходим всего лишь 1% правильных ответов).

Защита: К сожалению, защититься от данного вида атак невозможно. И к счастью, ИНС от Vicarious не будет использоваться для целенаправленных атак для обхода капчи на сайтах, т.к. она слишком дорогостоящая для таких мелких задач (сами производители говорят, что она представляет из себя кластер из множества серверов). Основная её область применения — это решение различных задач медицины и робототехники.

А взлом капчи с её помощью — это лишь демонстрация возможностей.

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

Обход капчи с помощью общедоступных сервисов

По мере развития систем OCR и ИИ меры усложнения графических капчей становились всё сложнее и сложнее, что позволяло их разработчикам прилагать колоссальные усилия при реализации. Но всё равно они оказывались тщетными, т.к. они не обеспечивали 100% защиту сайтов от автоматизированных атак.

Поэтому Google пошёл, как мне кажется, верным путём и решил просто изобрести новый стандарт noCAPTCHA, отказавшись от ручного ввода символов с картинок.programma-dlya-vvoda-kapchi-avtomatom

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

Но, несмотря на то, что данный стандарт появился достаточно недавно, в 2015 году, уже найден способ её автоматического решения. И он заключается далеко не в применении искусственного интеллекта.

Всё намного банальней — для прохождения Google reCAPTCHA достаточно использовать сервисы самого Google по распознаванию картинок и речи.

Распознавание картинок в случае с reCAPTCHA v2 (та самая noCAPTCHA) вряд ли поможет, т.к. при графических задачах нужно выбирать изображения, на которых присутствуют необходимые объекты, а не вводить изображённые символы, как это было в предыдущей версии.

А вот услуги сервиса Google Speech Recognition, являющийся одним из достижений Гугл в области искусственного интеллекта, о которых упоминалось в предыдущем способе обхода капчи, будет очень кстати. Поскольку сервис предоставляет API, то создать приложение на его базе не составляет труда.

Защита: к сожалению, в данной ситуации, как и в предыдущей, где для обхода капчи использовались ИНС, защититься от обхода капчи не удастся. Единственным положительным моментом снова является относительная доступность подходящих сервисов, т.к. Google даёт для их использования только тестовые $300.

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

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

Как пройти капчу, используя человеческий труд

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

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

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

Речь идёт об одном из современных способов добычи денег — заработке на вводе капчи, который появился, кстати, примерно тогда, когда CAPTCHA стала сложно распознаваемой программно.

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

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

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

  • автоматизации заработка;
  • рассылка спама;
  • скупка билетов и товаров в Интернет магазинах для более дорогой перепродажи;
  • взлом сайтов и т.д.

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

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

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

Естественно, мы долго не думаем, т.к. получить возможность скачать долгожданный фильм в HD качестве абсолютно бесплатно за проставление какой-то галочки в поле «Я не робот» — это просто мелочь. А в это время ваше действие по API используется для обхода капчи на другом стороннем сайте.

Отсюда мораль: всегда помните, что бесплатный сыр только в мышеловке и ничего бесплатного не бывает.

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

Обход капчи — выводы

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

Если от автоматизированных обходов капчи, использующих слабые места реализаций CAPTCHA ещё можно уберечься, устранив все проблемы с их безопасностью, то от ввода капчи реальными пользователями за деньги защититься просто невозможно.obkhod-kapchi-avtomatom-programmno

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

Также к «непобедимым» способам обхода капчи относятся технологии искусственного интеллекта, активно развивающиеся в последние годы.

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

Вспомнить ту же Google reCAPTCHA: поставь галочку, если Гуглу что-то не понравилось, выбери ещё и нужные картинки (с дорожными знаками, кстати, у меня до сих пор наблюдаются проблемы, т.к. я могу пройти такое задание где-то с 5 попытки). Не много ли возни для того, чтобы оставить комментарий или зарегистрироваться на сайте? Проще уже найти другой ресурс…

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

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

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

И не забывать делиться своими соображениями по поводу существующих способов обхода капчи и мер защиты от них в комментариях под статьёй :-)

the_posts_pagination(array( 'mid_size' => 3, 'prev_text' => __('« Предыдущая'), 'next_text' => __('Следующая »') ));