Кто сказал, что сессия может храниться только на стороне сервера?

Node.js

Сегодня я столкнулся со странной проблемой при использовании Koa, после чего внимательно изучил принцип реализации Koa-Session и освежил свои познания. Хорошо, давайте начнем с самого начала. Сначала посмотрите на принцип Session?

Что такое сессия

Механизм сеанса использует решение, которое поддерживает состояние на стороне сервера. За счет использования состояния на стороне сервера может поддерживаться. Клиент также обязан сохранить личность. Следовательно, механизму сеанса может потребоваться полагаться на механизм cookie для достижения цели сохранения удостоверения.

  1. При интервью с сервером создается первый визит клиента в сессию на стороне сервера, а затем сохраняется сессия (можно сохранить сессию в памяти, также можно хранить в редисе, рекомендуется использовать последнюю), затем эту сессию для создания уникальной строки идентификационных символов, а затем такой уникальной строки идентификации в заголовке ответа.
  2. подписать. На этом этапе sid подписывается секретным ключом, чтобы клиент не мог изменить sid. (необязательный шаг)
  3. Когда браузер получает ответ на запрос, он анализирует заголовок ответа, а затем сохраняет sid в локальном файле cookie.Браузер перенесет информацию о файле cookie под доменным именем в заголовок запроса следующего http-запроса.
  4. Когда сервер примет запрос клиента, он проанализирует sid в файле cookie заголовка запроса, а затем найдет сессию клиента, сохраненную сервером, в соответствии с sid, а затем решит, является ли запрос законным.

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

Странная коа-сессия

Что ж, посмотрим, сможет ли Koa-Session воспроизвести эту проблему.

const koa = require('koa')
const app = new koa()
const session = require('koa-session')

// 签名key keys作用 用来对cookie进行签名
app.keys = ['some secret'];

// 配置项
const SESS_CONFIG = {
  key: 'kkb:sess', // cookie键名
  maxAge: 86400000, // 有效期,默认一天
  httpOnly: true, // 仅服务器修改
  signed: true, // 签名cookie
};

// 注册
app.use(session(SESS_CONFIG, app));

// 测试
app.use(ctx => {
  if (ctx.path === '/favicon.ico') return;
  // 获取
  let n = ctx.session.count || 0;
  // 设置
  ctx.session.count = ++n;
  ctx.body = '第' + n + '次访问';
});

app.listen(3000)

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

Анализ причин

Теперь разберем его подробно. Прежде всего, я обнаружил, что значение поля cookie, в котором хранится sid, представляет собой значение, такое как eyXXXXX. Описание, скорее всего, json в кодировке base64. Не uuid, как мы обычно думаем об этом.Мы подтвердили этот результат онлайн-декодированием base64.Проблема становится ясной. Получается, что Koa-сессия действительно хранится на стороне клиента путем сериализации сессии по умолчанию. Мы также можем подтвердить это утверждение из следующей документации по npm.Ууууххххххххххххххххххххххххххххххххххх это и это лошадь плюс .com/package/

В документе четко указано, что хранилищем koa по умолчанию являются незашифрованные данные, размещенные на клиенте.

Преимущества и недостатки хранения клиентов

преимущество

Сначала поговорим о преимуществах. У хранилища на стороне клиента есть примерно два преимущества.

  • Недорогая реализация постоянства сеанса
  • Недорогая реализация проблемы с общим сеансом с несколькими экземплярами

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

недостаток

Есть две недостатки

  • Объем памяти ограничен (размер файла cookie обычно составляет 4 КБ)
  • Проблемы безопасности Конфиденциальные данные не могут быть сохранены, поскольку они хранятся на стороне клиента и не зашифрованы.

Как указать способ хранения

В Koa-Session, если вы хотите изменить метод хранения, вы можете реализовать интерфейс хранилища.

реализация памяти

Во-первых, давайте напишем память для достижения базы. На самом деле, просто ознакомиться с этим интерфейсом.

class Memory {
    constructor () {
        this.sotry = {}
    }
    
    get(key) {
        console.log('get:',key)
        return this.sotry[key]
    }

    set(key,sess) {
        console.log('set:',key,sess)
        this.sotry[key] = sess
    }
    destroy (key) {
        console.log('destroy:',key)
        this.sotry = {}
    }
}

const SESS_CONFIG = {
    key: 'kkb:sess', 
    store: new Memory() // 指定实现
}

app.use(session(SESS_CONFIG, app))

Вы видите указанное хранилище, Koa-session вызовет методы геттера и сеттера в интерфейсе хранилища.

Браузер также не хранит сериализованные данные, а хранит только sid или uuid.

полный код

GitHub.com/su37Джозеф Х…

Реализация Redis

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

const redisStore = require('koa-redis')
const redis = require('redis')
const redisClient = redis.createClient(6379, 'localhost')

const wrapper = require('co-redis')
const client = wrapper(redisClient)

app.keys = ['some secret']

const SESS_CONFIG = {
    key: 'kkb:sess', // 名
    store: redisStore({ client })
}

app.use(session(SESS_CONFIG, app))

Суммировать

Методом хранения Koa по умолчанию является метод сериализации на стороне клиента, который обновляет наше представление о подпрограмме Session. Этот метод фактически основан на методе реализации токена JWT. Идеально подходит для небольших приложений. Он может решить проблему устойчивости и горизонтального расширения при низких затратах.

Выявление проблем — это возможность для улучшения

Не забудьте поставить лайк и добавить в избранное