使用登录cookie的相对安全的方法是什么?

Sup*_*Spy 9 php cookies autologin

我想知道最安全的cookie登录方式是什么?如果您只是将通行证(使用salt加密)和用户名存储在cookie中并根据用户表进行验证,则潜在的攻击者可以窃取cookie并登录.人们通常不会检查'上次在线'.

那么"记住我的饼干"有更好的方法吗?IP不是一个好选择,是吗?(有些机器一直在更换IP).

Sup*_*Spy 20

我想我找到了一个聪明的解决方案!

这个(复杂的?)脚本的优点:

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

我在数据库中创建了一个包含以下信息的表:

    session | token | username | expire
Run Code Online (Sandbox Code Playgroud)

记住我的cookie将有这个设置:

    $value = "$session|$token|$userhash"; //Total length = 106
Run Code Online (Sandbox Code Playgroud)
  • Session 将是一个由40个(sha1)字符组成的字符串.
  • Token 将是一个32(md5)个字符的字符串.
  • Userhash 在cookie中将是一个32(用户名为md5)字符的字符串.
  • Username 在数据库中将是普通用户名.
  • Expire 现在将是+ 60天.

剧本:

if(isset($_SESSION['check']) || $_SESSION['check']){
    //User is logged in
}else if(isset($_COOKIE['remember']) && strlen($_COOKIE['remember'])==106){
    //THERE is a cookie, which is the right length 40session+32token+32user+2'|'
    //Now lets go check it...
    conncectdb(); //Sets connection
    //How do I protect this script form harmful user input?
    $plode = explode('|',$_COOKIE['remember']);
    $session = mysql_real_escape_string($plode[0]);
    $token = mysql_real_escape_string($plode[1]);
    $userhash = mysql_real_escape_string($plode[2]);
    $result = mysql_query(" SELECT user 
                FROM tokens 
                WHERE session = '$session' 
                AND token = '$token'
                AND md5(user) = '$userhash';")
    if(mysql_num_rows($result)==1){
        //COOKIE is completely valid!
        //Make a new cookie with the same session and another token.
        $newusername = mysql_result($result,0,0);
        $newsession = $session;
        $newtoken = md5(uniqid(rand(), true));
        $newuserhash = md5($username);
        $value = "$newsession|$newtoken|$newuserhash";
        $expire = time()+4184000;
        setcookie('remember', $value, $expire, '/', 'www.example.com', isset($_SERVER["HTTPS"]), true);
        mysql_query("   UPDATE tokens 
                SET token='$newtoken', expire='$expire'
                WHERE session = '$session' 
                AND token = '$token'
                AND md5(user)='$userhash';");
        //Set-up the whole session (with user details from database) etc...
    } else if(mysql_num_rows(mysql_query("SELECT user FROM tokens WHERE session = '$session' AND md5(user) = '$userhash';"))==1)){
        //TOKEN is different, session is valid
        //This user is probably under attack
        //Put up a warning, and let the user re-validate (login)
        //Remove the whole session (also the other sessions from this user?)
    } else {
        //Cookie expired in database? Unlikely...
        //Invalid in what way?
    }
} else {
    //No cookie, rest of the script
}
Run Code Online (Sandbox Code Playgroud)

脚本的优点:

  • 多次登录.您可以为您所在的每台计算机创建新会话.
  • Cookie和数据库将保持清洁.活跃用户每次登录都会更新cookie.
  • 开头的会话检查确保数据库不会得到无用的请求.
  • 如果攻击者窃取了cookie,它会获得一个新令牌,但不会获得新会话.因此,当真实用户使用旧(无效)令牌访问网站但使用有效的用户会话组合时,用户会收到潜在盗窃的警告.通过登录新会话重新验证后,攻击者持有的会话无效.重新验证确保受害者确实是受害者,而不是攻击者.

参考:http://jaspan.com/improved_persistent_login_cookie_best_practice


Gum*_*mbo 6

这种"记住我"功能总是存在额外的安全风险.

因为就像在会话中一样,你只有一个标识符,不仅可以识别用户(是谁?),而且还可以在不进行实际身份验证的情况下对该用户进行身份验证(是真的是他/她吗?).

但是与具有(或应该具有)短寿命(大多数不到一小时)的会话相反,并且标识符(或应该)定期更改(由于真实性/权限状态更改而基于时间和必要性) ,"记住我"标识符有效期为几天甚至几个月或几年!这种长期有效期会带来额外的安全风险.

因此,在询问如何实现这样一个"记住我"功能之前,您应该问问自己是否真的需要额外的安全风险.这主要取决于您的应用程序具有的资产以及身份验证的目的,以及您是否希望冒"模仿我"功能所带来的冒充/身份盗窃的风险.

如果是这样,请确保使用HTTPS提供基本安全性,并在cookie中设置HTTPOnly标志和安全标志.然后你可以做以下事情来构建这样一个"记住我"的功能:

  • 身份验证请求
    如果用户通过HTTPS进行身份验证并设置"记住我"选项,则生成一个随机记住我的令牌,将其存储在服务器端的"记住我"数据库中,并使用安全标记设置记住我的 cookie 值.然后开始一个新的会话并设置一个记住我的标志.

  • 任何其他要求

    1. 如果没有当前会话,通过HTTPS 重定向到记住我页面,检查是否有记住我的 cookie.如果有一个记住我的令牌并且它是有效的,则使其无效,生成一个新令牌,将其存储在"记住我"数据库中,使用该新令牌设置一个cookie并使用记住我标志集创建一个新会话.否则重定向到登录页面.
    2. 如果当前会话无效(确保使用严格的会话失效),如果设置了remember me标志,则通过HTTPS 重定向到remember me页面; 否则重定向到登录页面.

通过这种方式,身份验证通过HTTPS进行保护,包括初始身份验证和"记住我"身份验证.并且用户在当前会话期间仅是可信的; 如果它到期,则用户必须使用记住我令牌或提供他/她的登录凭证来重新进行身份验证.由于记住我的令牌存储在数据库中,用户可以使任何现有的记住我令牌无效.


Tha*_*hai 5

最流行的方式:

  • 许多脚本使用某种会话跟踪。当用户第一次访问网站时,它会为用户生成一个唯一的随机 ID,并将会话信息存储在服务器中,并将 ID 存储在 cookie 中。然后服务器使用唯一 ID(称为会话 ID)识别用户。与会话 ID 关联的信息只能由服务器看到。PHP 默认使用这个,

  • 有些将用户数据存储在 cookie 本身中,但具有使用秘密字符串作为密钥的 HMAC 签名。如果签名不匹配,脚本将丢弃 cookie。这样,服务器不必将会话数据保存在服务器上。用户通过查看 cookie 来查看会话中的内容,因此您不应在其中存储敏感数据。仅用户 ID(可能还有登录时间和 cookie 到期时间)就足够了。虽然用户可以看到会话信息中的内容,但 cookie 中的签名确保用户不能自己修改会话数据。

这些方式提供了一些安全性,即用户不能篡改会话数据,但不能保护用户免受窃听。他们总是可以使用数据包嗅探器并从任何开放的 WiFi 网络窃取会话。某些应用程序确实依赖于用户 IP,但攻击者是否在同一网络中并不重要。有些应用依赖 User-Agent,但当用户更新浏览器或从其他浏览器导入数据时就会出现问题。

如果您真的很关心安全性,请使用 HTTPS

另请阅读这篇文章,尤其是名为网站运营商如何解决问题的部分?