一种验证会话cookie而不存储它们的方法

时间:2017-09-03 03:55:44

标签: security session cookies hash backend

基本信息

  • 我有一个网络服务器,里面装着所有那些花哨的东西。
  • 它在我的半土豆PC上运行,因此我没有任何免费的64TB SSD存储空间。
  • 我必须关心可扩展性,因为有一天我可能会有 1000 用户。
      

    哇,这样的用户,非常多!

  • 如果用户丢失了设备,我不希望任何密码被盗。所以我决定使用会话。
  • 我不想存储所有用户会话,因为这可能是 100 的设备。所以1000 * 100是很多会话cookie。
  • 我想到了不存储的方式,而是验证会话以检查请求是否来自帐户所有者。

结构

全局

// Secret 128 bytes array.
const ByteArray serverMagic;

// Generates a SHA512 hash based on data.
function hash(ByteArray data);

// Encodes array of bytes into base64 string.
function base64(ByteArray data);

// Returns current time on the server.
function getCurrentDate();

// Returns userMagic based on the user ID.
function getUserMagic(Integer uid);

// Returns true if user entered wrong password.
function isLoginInvalid(Integer uid, String password);


function Object.toShortString(); // Encodes an object into a short ASCII string.

对于每个用户

const Integer uid; // User ID.
var String password; // Secret code that gives you all of that damn power.
var ByteArray userMagic // Secret 128 bytes array.

逻辑

如果用户想要登录

他将发送:

  • 会话到期日期(因此cookie在所需的时间后无效)
  • 用户ID
  • 密码(或密码的哈希,它并不重要)


function logIn(Date expire, Integer uid, String password) {
  if(isLoginInvalid(uid, password)) then
    return error;

  String encExpire = expire.toShortString();
  String encUID = uid.toShortString();

  ByteArray userMagic = getUserMagic(uid);

  ByteArray food = encExpire + '_' + serverMagic + userMagic + '_' + encUID;
  ByteArray hash = hash(food);

  String session = encExpire + '_' + encUID + '_' + base64(hash);
  return session;
}

客户端将保存该会话cookie。

如果用户将采取一些行动

他将会话cookie发送到服务器。

// After parsing session cookie
function request(Date sessionExpire, Integer uid, ByteArray sessionHash) {
  if(sessionExpire < getCurrentDate()) then
    return error;

  String encExpire = sessionExpire.toShortString();
  String encUID = uid.toShortString();

  ByteArray userMagic = getUserMagic(uid);

  ByteArray food = encExpire + '_' + serverMagic + userMagic + '_' + encUID;
  ByteArray hash = hash(food);

  if(hash == sessionHash) then
    return success;
  else
    return error;
}

如果用户想要使所有会话无效

由于设备丢失或密码更改,服务器只能生成新的userMagic,这会使以前的所有会话cookie无效。

问题

  • 存储是不是存储会话的好方法吗?
  • 我的系统有缺陷吗?
  • 可以破解吗?
    • 怎么会被破解?
  • 如何滥用?
  • 如何改进我的系统?

1 个答案:

答案 0 :(得分:0)

修订回答:

像这样的解决方案的问题是它们经常容易受到非常微妙的错误的攻击,例如length extension attacks。保持安全,然后使用HMAC

仅供参考.Net有一些与此不同的构造,但使用HMAC并且没有用户魔力。

上一页,缩回答案:

任何用户都可以计算:

String session = encExpire + '_' + encUID + '_' + base64(hash);

这意味着任何用户都可以创建任意会话。黑客将使用设置为管理员uid的encUID来执行此操作,该管理员可以是1或0或类似的东西。

我可能会建议使用带有密钥的HMAC修复此错误,但您真的不应该自己实现这个。找到一个广泛使用且经过充分研究的库,为您进行会话管理,而不是试图重新发明轮子。