Хранение сессии на клиенте

Как вы, должно быть, знаете, хранить пользовательские данные на клиентской стороне плохо: их ведь может подделать злостный хакер. Но сегодня я вам расскажу, как можно безопасно хранить сессионные данные, не волнуясь за их сохранность. Расскажу на примере Snap Framework, на котором и написан этот блог.

Суть метода — шифрование (кто бы мог подумать). Snap для своих сессий использует библиотеку Web.ClientSession, а поэтому что и как обрабатывается можно смело подсмотреть в документации:

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

Skein — это просто хороший алгоритм хеширования. К сожалению, он не победил в конкуре на замену SHA-2, и название SHA-3 получил другой алгоритм. Поэтому самое время заменить Skein на новоявленный SHA-3 — Keccak.

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

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

Хозяйке на заметку: чтобы вашу сессию нельзя было увести с помощью JavaScript, добавьте в заголовок Set-Cookie параметр HttpOnly. Куки с таким параметром не появляются в document.cookie.

Осталась одна загадка, связанная с моим сайтом. Кука _session передается как сессионная и должна удаляться с закрытием браузера. Так и происходит в Opera, но не Google Chrome и Firefox. Может есть какая-то стандартизированная или неофициальная фича, которая не дает сессионным кукам удалиться?

Печаль

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

Сотый счастливый пост
Две последовательные поездки

Две последовательные поездки. Вот счастье-то!

Ошибки bingbot/msnbot

Как же я люблю Microsoft. Вот, например, есть у них поисковик Bing (им, кстати, кто-нибудь пользуется?). Авторы crawler’ов для этого поисковика совершенно не умеют работать с UTF-8. Почему-то только они присылают запросы с неверно закодированными кириллическими буквами.

Пример. Есть страница «работа» :: [dikmax’s blog]. Везде в ссылках на эту страницу у меня написано <a href=”/tag/работа”>.

Какую страницу запрашивают все браузеры и поисковики: /tag/%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0. А что же пытается получить msnbot: /tag/%D1%E2%82%AC%D0%B0%D0%B1%D0%BE%D1%E2%80%9A%D0%B0.

            D1                (incomplete sequence)
U-000020AC  E2 82 AC         
U-00000430  D0 B0            
U-00000431  D0 B1            
U-0000043E  D0 BE            
            D1                (incomplete sequence)
U-0000201A  E2 80 9A         
U-00000430  D0 B0            

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

Решение понятно, нужно кодировать ссылки на стороне сервера. Но зачем, если и так всё работает? А Bing — не тот поисковик, под который стоит подстраиваться. Хотя когда-нибудь я поправлю и это.

Скоро!

Во всех известных поисковиках!

Все ваши комментарии!

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

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

{
  "code":0,
  "response":[
    {
      "forum":"dikmax",
      "parent":667510883,
      "author":{
        "username":"google-1b379da98470c64a0c4bc8c2230d616d",
        "about":"",
        "name":"...",
        "url":"",
        "joinedAt":"2012-09-25T03:14:42",
        "avatar":{
          "permalink":"...",
          ...
        },
        ...
      },
      "message":"...",
      ...
    },
    ...
  ]
}

Приблизительный процесс разбора:

  1. Что делать, если результат не является правильным JSON.
  2. Что делать, если корневой узел — не объект.
  3. Что делать, если у объекта нет свойства code.
  4. Если code — не является числом.
  5. Если code всё-таки число, но не 0.
  6. Если у объекта нет свойства response.
  7. Если response — не массив.
  8. Преобазовываем response в два массива: первый с комментариями, второй с ошибками разбора комментариев.

И когда какого-то «если» нет, компилятор выдаст ошибку и придется искать, какой вариант ты еще не предусмотрел. Т.е. компилятор заботится, чтобы твоя программа умела работать при любых данных. И это, конечно, огромный плюс программирования на Haskell.

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

← СтаршеМоложе →