3

我有兴趣在remember me登录页面上编写一个功能,该功能将在个人计算机上记录一个 cookie 多长时间。我知道这样做有危险,所以我想确保我以正确的方式做这件事。

我听说有人在数据库表和 cookie 之间创建链接以进行验证;但是,不确定如何执行此操作或是否建议这样做。我是 cookie 的新手,所以请解释一下最好的方法。我没有任何示例,因为就像我说的那样,我以前从未编写过此代码,并且希望确保我以正确的方式进行操作,并从做过的人那里获得输入。

我不确定 facebook 的 cookie 是否永远存在,我只知道在我的电脑上我永远不需要重新登录,除非我删除我的历史记录。所以我可能想像他们那样做。

提前致谢!

4

3 回答 3

3

迄今为止,我所见过的持久 cookie 的最佳技术之一是Barry Jaspan 的

  1. 当用户在选中记住我的情况下成功登录时,除了标准会话管理 cookie 之外,还会发出一个登录 cookie。
  2. 登录 cookie 包含用户的用户名、系列标识符和令牌。系列和令牌是来自适当大空间的不可猜测的随机数。这三者一起存储在数据库表中。
  3. 当未登录用户访问该站点并显示登录 cookie 时,会在数据库中查找用户名、系列和令牌。
    1. 如果存在三元组,则认为用户已通过身份验证。使用的令牌将从数据库中删除。生成一个新令牌,并使用用户名和相同的系列标识符存储在数据库中,并向用户发出一个包含所有三个的新登录 cookie。
    2. 如果存在用户名和系列但令牌不匹配,则假定为盗窃。用户会收到措辞强硬的警告,并且用户记住的所有会话都将被删除。
    3. 如果用户名和系列不存在,则忽略登录 cookie。

我建议你阅读整篇文章,以上是要点。

此外,您将希望仅通过 SSL 连接发出这些 cookie 并在其上设置securehttponly标志。

由于这意味着用户仅在通过 SSL 连接到服务器时才通过身份验证,因此我另外设置了Strict-Transport-SecurityHTTP 标头以强制浏览器将来始终使用 SSL,另外还设置了一个简单的 cookie,例如persistent_login_available=yes用于非 SSL 连接。如果浏览器通过非 SSL 连接访问站点并且服务器看到persistent_login_availablecookie,它会将访问者重定向到 SSL 版本并通过安全 cookie 对用户进行身份验证。

通过此过程,您将尽可能安全。不过,根据您的需要,这可能有点过头了,您自己决定。

于 2013-03-16T21:04:18.660 回答
3

我还没有为自己编写代码,但我会这样处理这个问题:

1.创建一个表,当用户为持久性提供 cookie 时,该表可用于强制进行有效性检查:

create table RememberMe
(
   user_id    int(10)  NOT NULL,
   user_token char(10)  NOT NULL,
   token_salt int(6)   NOT NULL,
   time       int(10)  NOT NULL,
   PRIMARY KEY (user_id),
   CONSTRAINT nameYourConstraint 
              FOREIGN KEY (user_id) 
              REFERENCES userTableName (whatever_user_id_equals)
)

要填充此表,我将在登录名中添加一些代码行,对于此示例,我将使用伪代码

// userID variable has been sanitized already so
// check if user clicked remember me
// and if the user logged in successfully:
if ( rememberMe == checked && login() == true )
{
     // random number to serve as our key:
     randomNumber = random( 99, 999999  );

     // convert number to hexadecimal form:
     token = toHex( ( randomNumber**randomNumber ) );

     // encrypt our token using SHA1 and the randomNumber as salt
     key = encrypt( token, randomNumber, SHA1 );

     // get the number of seconds since unix epoch:
     // (this will be 10 digits long until approx 2030)
     timeNow = unix_time()

     // check to see if user is in table already:
     sql = "SELECT user_id FROM RememberMe
            WHERE user_id = 'userID'";

     // connect to database:
     db = new DBCon();
     
     result = db->query( sql );
     
         // number of rows will always be 1 if user is in table:
         if ( result->rows != 1 )
             exists = true;
         else 
             exists = false;
     
     result->free_memory();
     
         if ( exists == true )
         {
             sql = "UPDATE RememberMe SET
                    user_id    = 'userID'
                    user_token = 'token'
                    token_salt = 'randomNumber'
                    time       = 'timeNow'";
         }
         else
         {
             sql = "INSERT INTO RememberMe
                    VALUES( 'userID', 'token', 'randomNumber', 'timeNow' )";
         }
     
     result = db->query( sql );
     
         // the affected rows will always be 1 on success
         if ( result->affected_rows != 1 )
         {
            print( "A problem occurred.\nPlease log in again." );
            quit();
         }

     result->free_memory();

     // create a new cookie named cookiemonster and store the key in it:
     // (we're not actually storing a score or birthday, its a false flag)
     set_cookie( "CookieMonster", escape("score="+ userID +"birthday="+ key );
}

这段代码的作用是检查用户是否检查了记住我,并使用用户的键、令牌和盐以及时间填充数据库表(以便您可以对记住我实施时间限制特征)。

从这里您可以向您的网站添加代码,检查是否设置了CookieMonster cookie,如果设置了,您可以按照以下步骤强制执行其有效性:

  1. 从提供的 cookie 中提取用户 ID 和密钥

  2. 用userID查询数据库看是否

       --> a) user has requested to be remembered
    
       --> b) check the time to see if they cookie is still valid
    
       --> c) extract the token and salt from database table record
    
  3. 通过 encrypt() 函数调用运行令牌和盐,并与提供的密钥匹配。

  4. 如果一切顺利,请创建一个新会话并让用户登录。

现在,每次用户访问您的站点时,他们都会登录,并且如果他们的计算机遭到入侵,攻击者将无法访问他们的密码

旁注:您应该始终要求您的用户在更改密码或电子邮件时提供密码,这样如果用户的 cookie 落入坏人之手,您的攻击者将无法窃取该帐户。

于 2013-03-16T22:46:54.773 回答
2

这个策略被认为是最佳实践:看看这篇文章:http: //jaspan.com/improved_persistent_login_cookie_best_practice

于 2013-03-16T21:03:07.200 回答