Создание личной записной книжки на php/mysql с шифрование

от автора

Доброго времени суток!

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

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

Личный дневник использует два внешних php класса

  • XTEA — для шифрования
  • SafeMySQL — для работы с базой данных

Имеет очень простую структуру базы данных
CREATE TABLE `notest` ( `id` int(255) NOT NULL, `text` text NOT NULL, `date_d` text NOT NULL, `date_m` text NOT NULL, `date_t` text NOT NULL, `date_cat` text NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Ключ, который использует система хранится в переменной $_SESSION[‘key’]
Проверяем её состояние, спрашиваем у пользователя ключ, если этой переменной нет

// Если не существует переменная ключа   if (!isset($_SESSION['key'])) {     $keyw = '<form action="" method="post"><input type="text" name="key" placeholder="Введите ваш ключ"><input type="submit" value="Сохранить"></form>';   }   // Иначе, если существует   else {     $keyw = '<button><a class="nodec_link" href="index.php?action=delkey">Удалить ключ</a></button>';   }   // Если отправлена форма сохранения ключа   if (isset($_POST["key"])) {     $_SESSION['key'] = $_POST["key"];     header("Location: index.php");     exit();   } 

Когда пользователь закончил работу, делаем unset

if ((isset($_GET['action'])) && ($_GET['action'] == 'delkey')) {     unset($_SESSION['key']);     header("Location: index.php");     exit();   } 

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

$db = new SafeMySQL($set_bd); $option = $db->getAll("SELECT DISTINCT `date_cat` FROM `notes`"); foreach ($option as $value) { $desc_opt = explode("-", $value['date_cat']);  echo '<option value="index.php?date='.$value['date_cat'].'">'.num2name($desc_opt[0]).' '.$desc_opt[1].'</option>'; } 

Функция num2name() переводит номер месяца в его название

function num2name($num) {     switch ($num) {       case '01':         $name = "январь";         break;       case '02':         $name = "февраль";         break;       case '03':         $name = "март";         break;       case '04':         $name = "апрель";         break;       case '05':         $name = "май";         break;       case '06':         $name = "июнь";         break;       case '07':         $name = "июль";         break;       case '08':         $name = "август";         break;       case '09':         $name = "сентябрь";         break;       case '10':         $name = "октябрь";         break;       case '11':         $name = "ноябрь";         break;       case '12':         $name = "декабрь";         break;              default:         $name = "";         break;     }     return $name;   } 

В зависимости от наличия запроса на вывод записей определённого месяца, выводим записи дневника

// Если отправлен запрос на конкретный месяц               if (isset($_GET["date"])) {                 $cur_date = $_GET["date"];                 $db = new SafeMySQL($set_bd);                 $data = $db->getAll("SELECT * FROM `notes` WHERE `date_cat` = ?s ORDER BY `id` DESC", $cur_date);                 foreach ($data as $key) {                   // Декодируем текст                   $xtea = new XTEA($_SESSION['key']);                   $text_decode = $xtea->Decrypt($key["text"]);                   // Выводим записи                   echo '<tr>                     <td class="date">                       <div class="date_m">'.num2name($key["date_m"]).'</div>                       <div class="date_d">'.$key["date_d"].'</div>                       <div class="date_t">'.$key["date_t"].'</div>                     </td>                     <td class="note_text" valign="top">'.$text_decode.'</td>                   </tr>';                 }               }               // Если нет запроса на определённый месяц, выводим последние $set_col записей               else {                 $db = new SafeMySQL($set_bd);                 $data = $db->getAll("SELECT * FROM `notes` ORDER BY `id` DESC LIMIT ?i", $set_col);                 foreach ($data as $key) {                   // Декодируем текст                   $xtea = new XTEA($_SESSION['key']);                   $text_decode = $xtea->Decrypt($key["text"]);                   // Выводим записи                   echo '<tr>                     <td class="date">                       <div class="date_m">'.num2name($key["date_m"]).'</div>                       <div class="date_d">'.$key["date_d"].'</div>                       <div class="date_t">'.$key["date_t"].'</div>                     </td>                     <td class="note_text" valign="top">'.$text_decode.'</td>                   </tr>';                 }               }  


Добавление новой записи происходит через простую форму

<form method="post" action=""> <textarea rows="10" name="text" placeholder="Текст новой записи"></textarea> <input type="submit" value="Добавить"> </form> 

Которая обрабатывается таким кодом

if (isset($_POST["text"])) { // Получение данных в переменные $text = nl2br($_POST["text"]); // Шифрование текста $xtea = new XTEA($_SESSION['key']); $text = $xtea->Encrypt($text);  $date_d = date("d"); $date_m = date("m"); $date_t = date("Y"); $date_cat = date("n-Y"); // Отправка в базу данных $db = new SafeMySQL($set_bd); $sql  = "INSERT INTO `notes` (`text`, `date_d`, `date_m`, `date_t`, `date_cat`) VALUES (?s, ?s, ?s, ?s, ?s)"; $db->query($sql, $text, $date_d, $date_m, $date_t, $date_cat); } 

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

Полный код основного файла

<?php   // Отображение ошибок на странице   ini_set('error_reporting', E_ALL);   ini_set('display_errors', 1);   ini_set('display_startup_errors', 1);    include "config.php";   include "db.php";   include 'xtea.php';    header('Content-Type: text/html; charset=utf-8');   session_start();    // Если не существует переменная ключа   if (!isset($_SESSION['key'])) {     $keyw = '<form action="" method="post"><input type="text" name="key" placeholder="Введите ваш ключ"><input type="submit" value="Сохранить"></form>';   }   // Иначе, если существует   else {     $keyw = '<button><a class="nodec_link" href="index.php?action=delkey">Удалить ключ</a></button>';   }   // Если отправлена форма сохранения ключа   if (isset($_POST["key"])) {     $_SESSION['key'] = $_POST["key"];     header("Location: index.php");     exit();   }   if ((isset($_GET['action'])) && ($_GET['action'] == 'delkey')) {     unset($_SESSION['key']);     header("Location: index.php");     exit();   }   // если отправлена форма добавления записи   if (isset($_POST["text"])) {     $text = nl2br($_POST["text"]);      $xtea = new XTEA($_SESSION['key']);     $text = $xtea->Encrypt($text);      $date_d = date("d");     $date_m = date("m");     $date_t = date("Y");     $date_cat = date("n-Y");      $db = new SafeMySQL($set_bd);     $sql  = "INSERT INTO `notes` (`text`, `date_d`, `date_m`, `date_t`, `date_cat`) VALUES (?s, ?s, ?s, ?s, ?s)";     $db->query($sql, $text, $date_d, $date_m, $date_t, $date_cat);   }    // Функия перевода номера месяца в его название   function num2name($num) {     switch ($num) {       case '01':         $name = "январь";         break;       case '02':         $name = "февраль";         break;       case '03':         $name = "март";         break;       case '04':         $name = "апрель";         break;       case '05':         $name = "май";         break;       case '06':         $name = "июнь";         break;       case '07':         $name = "июль";         break;       case '08':         $name = "август";         break;       case '09':         $name = "сентябрь";         break;       case '10':         $name = "октябрь";         break;       case '11':         $name = "ноябрь";         break;       case '12':         $name = "декабрь";         break;              default:         $name = "";         break;     }     return $name;   } ?> <!DOCTYPE html> <html lang="ru"> <head>     <meta charset="utf-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="width=device-width, initial-scale=1">     <link href='https://fonts.googleapis.com/css?family=Open+Sans&subset=latin,cyrillic' rel='stylesheet' type='text/css'>     <title><?php echo $set_title; ?></title>     <link href="style.css" rel="stylesheet"> </head> <body>     <div class="main">       <table>         <tr>             <select onchange="location.href=this.options[this.selectedIndex].value;">               <option value="index.php">Выбор месяца и года</option>               <option value="index.php">Последине <?php echo $set_col; ?> записей</option>               <?php                 $db = new SafeMySQL($set_bd);                 $option = $db->getAll("SELECT DISTINCT `date_cat` FROM `notes`");                 foreach ($option as $value) {                   $desc_opt = explode("-", $value['date_cat']);                   echo '<option value="index.php?date='.$value['date_cat'].'">'.num2name($desc_opt[0]).' '.$desc_opt[1].'</option>';                 }               ?>             </select>         </tr>         <tr>           <?php echo $keyw; ?>         </tr>       </table>       <h1><?php echo $set_title; ?></h1>       <div class="addform">         <form method="post" action="">           <textarea rows="10" name="text" placeholder="Текст новой записи"></textarea>           <input type="submit" value="Добавить">         </form>       </div>       <div class="notes">         <table class="table">           <tbody>             <?php                // Если отправлен запрос на конкретный месяц               if (isset($_GET["date"])) {                 $cur_date = $_GET["date"];                 $db = new SafeMySQL($set_bd);                 $data = $db->getAll("SELECT * FROM `notes` WHERE `date_cat` = ?s ORDER BY `id` DESC", $cur_date);                 foreach ($data as $key) {                   // Декодируем текст                   $xtea = new XTEA($_SESSION['key']);                   $text_decode = $xtea->Decrypt($key["text"]);                   // Выводим записи                   echo '<tr>                     <td class="date">                       <div class="date_m">'.num2name($key["date_m"]).'</div>                       <div class="date_d">'.$key["date_d"].'</div>                       <div class="date_t">'.$key["date_t"].'</div>                     </td>                     <td class="note_text" valign="top">'.$text_decode.'</td>                   </tr>';                 }               }               // Если нет запроса на определённый месяц, выводим последние $set_col записей               else {                 $db = new SafeMySQL($set_bd);                 $data = $db->getAll("SELECT * FROM `notes` ORDER BY `id` DESC LIMIT ?i", $set_col);                 foreach ($data as $key) {                   // Декодируем текст                   $xtea = new XTEA($_SESSION['key']);                   $text_decode = $xtea->Decrypt($key["text"]);                   // Выводим записи                   echo '<tr>                     <td class="date">                       <div class="date_m">'.num2name($key["date_m"]).'</div>                       <div class="date_d">'.$key["date_d"].'</div>                       <div class="date_t">'.$key["date_t"].'</div>                     </td>                     <td class="note_text" valign="top">'.$text_decode.'</td>                   </tr>';                 }               }              ?>           </tbody>         </table>       </div>      </div>    </body> </html> 

Ссылки
Исходный код в репозитории
SafeMySQL
Алгоритм XTEA

ссылка на оригинал статьи http://habrahabr.ru/post/273587/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *