Безопасная передача клиенту логинов/паролей с помощью WordPress

Сегодня на хабре увидел интересный пост «А как Вы передаете клиентам логины/пароли?»

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

Среди плюсов числятся AES-шифрование базы, вход по https и возможность добавления пароля для просмотра.

Среди минусов — сам факт того, что это сторонний сервис. В записи «WordPress как собственный сервис закладок» я уже говорил, что, если есть возможность реализовать какой-то сервис на собственном сервере — нужно это делать.

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

Первое, что нужно сделать, очевидно, — это как-то обособить записи, предназначенные для одноразового просмотра. Сделать этом можно как минимум тремя способами: отдельная рубрика/метка для таких постов, произвольные поля и custom post type. В принципе, функционал, описываемый в этой записи, годится не только для передачи паролей, поэтому каждому нужно решить для себя, что ему лучше использовать. Кому-то может показаться проще ставить галочку в правой колонке при создании нового поста, но я хочу рассказать конкретно про custom post type, так как это, во-первых, логичней, а во-вторых, лишает необходимости шаманить с выдиранием записей из потока (главная, архивы, RSS и т.д.).

Добавим новый тип записей, используя register_post_type():

// Регистрируем новый тип записи
function custom_safe_post_type()  {
	$labels = array(
		'name'                => 'Безопасные сообщения',
		'singular_name'       => 'Безопасное сообщение',
		'menu_name'           => 'Безопасные сообщения',
		'all_items'           => 'Все сообщения',
		'view_item'           => 'Показать сообщение',
		'add_new_item'        => 'Добавить новое сообщение',
		'add_new'             => 'Новое сообщение',
		'edit_item'           => 'Редактировать сообщение',
		'update_item'         => 'Обновить сообщенеи',
		'search_items'        => 'Поиск сообщений',
		'not_found'           => 'Ничего не найдено',
		'not_found_in_trash'  => 'В корзине ничего не найдено',
	);

	$args = array(
		'label'               => 'safe',
		'description'         => 'Безопасные сообщения',
		'labels'              => $labels,
		'taxonomies'          => array( ); // Для нашего типа записей не должны использоваться ни категории, ни метки
		'hierarchical'        => false,
		'public'              => true,
		'show_ui'             => true,
		'show_in_menu'        => true,
		'show_in_nav_menus'   => false, // Исключаем возможность добавления страницы в кастомные меню
		'show_in_admin_bar'   => true,
		'supports' => array( 'title', 'editor' ), // Оставляем только те элементы редактирования поста, которые нам нужны
		'menu_position'       => 5,
		'can_export'          => false, // Убираем возможность экспортировать запись с помощью инструмента "Экспорт"
		'has_archive'         => false, // Убираем архивную страницу
		'exclude_from_search' => true, // Обязательно исключаем эти посты из поиска
		'publicly_queryable'  => false, // Не даем возможности показать пост как либо еще, кроме прямой ссылки
		'capability_type'     => 'page',
	);

	register_post_type( 'safe', $args );
}

// Цепляем к 'init'
add_action( 'init', 'custom_safe_post_type', 0 );

Пол-работы сделано. Осталась вторая половина: сделать так, чтобы эти записи отображались и сделать так, чтобы они удалялись после первого просмотра. Для отображения есть два варианта. Первый — использовать специально созданный для нового типа поста шаблон single-safe.php. Второй способ — использовать is_singular() в оригинальном loop’е (в зависимости от темы, код вывода loop может находиться в файлах single.php, content.php, loop.php и т.д., смотрите сами). Если не хотите создавать новый шаблон, можете просто использовать в вышеупомянутых файлах следующее условие:

if (is_singular( 'safe' ) {
//нужный контент
}

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

Это переместит запись в корзину сразу же после её первой загрузки. Не забудьте где-нибудь жирно указать, что данная страница загружена в первый и последний раз, и попытка обновить её или переслать ссылку кому-нибудь другому приведет к ошибке 404 =)

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

Будьте осторожны и не экспериментируйте на живых установках. Функции wp_trash_post() и wp_delete_post() никак не проверяют наличие прав администратора, и в том виде, в котором я их привел, удаляют пост без какого-либо запроса подтверждения. Я снимаю с себя любую ответственность за случайно удаленные посты =)

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

P.S. Для тех, кому не терпится попробовать. Рассказываю самый-самый простой и быстрый способ сделать то, о чем говорится в этой записи:

  1. Сделать копию файла page.php, переименовать её в page-safe.php
  2. В начале файла вставить код
  3. В конце (но перед endwhile;) вставить код

Готово. Создавайте новую страницу, используя для неё шаблон «Безопасное сообщение». Посмотреть её можно будет только один раз.

UPD. (24.01.13): Про защиту поста паролем. Всё ок, только, к сожалению, пост после ввода пароля посмотреть уже не получается, потому что он удаляется =)
Для исправления этой печальки, обернем wp_trash_post() функцией post_password_required():

Добавить комментарий