为“记住我”功能设置cookie的最安全方式

时间:2013-03-16 20:55:17

标签: php cookies

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

我听说有人在数据库表和cookie本身之间建立链接以进行验证;但是,不知道如何做到这一点或是否建议。我是饼干的新手,所以请尽可能地解释一下。我没有任何例子,因为就像我说的那样,我以前从未对此进行过编码,并希望确保以正确的方式进行,并从已完成此操作的人那里获得输入。

我不确定facebook的饼干是否会永久存在,我只知道在我的电脑上我从未真正重新登录,除非我删除了我的历史记录。所以我可能想要这样做的方式类似。

提前致谢!

3 个答案:

答案 0 :(得分:3)

我见过的最好的持久性Cookie技术之一是Barry Jaspan's

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

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

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

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

通过这个过程,您可以尽可能地保证安全。根据您的需要,可能可能会超出您的需求,您决定。

答案 1 :(得分: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.   
  3. 使用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
    
  4.   
  5. 通过encrypt()函数调用运行token和salt并匹配   提出的密钥。

  6.   
  7. 如果一切都结束,请创建一个新会话并将用户登录。

  8.   

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

备注:您应该始终要求您的用户在更改密码或电子邮件时提供密码,这样一来,如果用户的cookie找不到您的方式,攻击者将无法窃取该帐户。

答案 2 :(得分:2)

此策略被认为是最佳做法:请查看以下文章:http://jaspan.com/improved_persistent_login_cookie_best_practice