Каков правильный способ генерации сеанса и чем проверять его при каждом запросе?
Регистрация и первоначальная аутентификация (проверка личности пользователя для генерации сеанса) обрабатывается внешней службой, поэтому об этом не может быть и речи.
Чтобы упростить вопрос, каков собственный безопасный способ создания и шифрования сеанса с секретом.
Требования (альтернативы приветствуются) :
- Сессия должна состоять из двух частей: одна хранится в файлах cookie, вторая - в базе данных.
- Проверка пользователя обрабатывается сервером с использованием части сеанса базы данных, части куки и функции проверки.
- Функции создания и проверки сеансов, хранящиеся на стороне сервера и недоступные для пользователя.
- Если часть или функции сеанса базы данных скомпрометированы, хакер не может сделать запрос, выдавая себя за пользователя. Для этого ему нужно будет украсть пользовательские файлы cookie или функцию создания сеанса и часть сеанса базы данных.
- Поддержка нескольких устройств с одной и той же частью сеанса базы данных.
- JWT не может использоваться, поскольку требуется выход из системы на сервере сторона (часть сеанса базы данных будет удалена, и все устройства не смогут войти со старой частью сеанса файлов cookie). У пользователя был некоторый уровень доверия, который может измениться, и это потребует аннулирования JWT, поэтому сеансы - лучший выбор.
Я думал об использовании Crypto AES для этого, но после спрашивал "все ли в порядке?" ?"- ответ был" нет ", я не специалист по криптографии, поэтому я не до конца понял причину.
Вот моя первоначальная идея реализации:
/**
* @param {string} data dummy
* @param {string} userKey from database or create new
* @return {object} {iv, key, encryptedData}
*/
function encrypt(data, userKey) {
let key = userKey ? Buffer.from(userKey, 'hex') : crypto.randomBytes(32)
let iv = crypto.randomBytes(16)
let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv)
let encrypted = cipher.update(data)
encrypted = Buffer.concat([encrypted, cipher.final()])
return { iv: iv.toString('hex'), key: key.toString('hex'), encryptedData: encrypted.toString('hex') }
}
/**
* @param {string} iv
* @param {string} key
* @param {string} encryptedData
* @return {string} decrupted dummy data
*/
function decrypt(iv, key, encryptedData) {
try {
iv = Buffer.from(iv, 'hex')
key = Buffer.from(key, 'hex')
encryptedData = Buffer.from(encryptedData, 'hex')
let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
let decrypted = decipher.update(encryptedData)
decrypted = Buffer.concat([decrypted, decipher.final()])
return decrypted.toString()
} catch (err) {
return false
}
}