17

我是在 PHP 中处理登录脚本的初学者。这是我到目前为止的表单令牌声明:

$_SESSION["form_token"] = md5(rand(time (), true)) ;

该语句在用户表示他/她想要登录之后立即发出。

我有限的理解是,token 的目的是在唯一的时间点识别唯一的用户,并伪装表单 token 信息。

然后一切变得模糊。这是我的 3 个未解决的问题:

  1. 出于安全目的“检查”表单令牌的最佳时间是什么时候?

  2. 我该如何检查?

  3. 如果有的话,我什么时候“销毁”表单令牌?(IOW,表单令牌会在用户注销之前保持“活动”吗?

4

3 回答 3

19

这是为了防止 CSRF 攻击

http://en.wikipedia.org/wiki/Cross-site_request_forgery

理论上,恶意站点可以显示一个发布到您的应用程序的表单。该表格可能包含导致数据泄露或某些不需要的操作的说明。用户可能会被欺骗提交应用程序接受的表单,因为用户已经登录。表单令牌确保表单是由您的站点而不是其他站点创建的。

检查 HTTP_REFERER 通常足够好,但不是完整的解决方案(例如,https 不会发送引荐来源网址字符串)。

如果您真的想使用令牌保护所有表单,您可以创建一些方便的函数,如 emitToken() 和 checkToken() ,这将使其在站点范围内工作。

一些例子:

http://phpsec.org/projects/guide/2.html

http://www.rodsdot.com/php/CSRF_Form_Protection.php

于 2010-01-09T17:54:03.607 回答
15

没有必要做你正在尝试的事情。当您在 PHP 中使用 session_start() 启动会话时,已经为您生成了一个唯一的 SESSIONID。你应该把它放在表格上。默认情况下通过 cookie 处理。也不需要检查 SESSIONID,它再次为您处理。

您负责对用户进行身份验证并存储他们经过身份验证的身份(例如 $_SESSION['user_id'] = $userId 在 SESSION 中。如果用户注销,您将使用 session_destroy 销毁他们的会话。

您应该确保 session_start() 是您网站中所有页面的首要任务之一。

这是一个基本示例:

<?php
session_start(); // starts new or resumes existing session
session_regenerate_id(true); // regenerates SESSIONID to prevent hijacking

function login($username, $password)
{
    $user = new User();
    if ($user->login($username, $password)) {
        $_SESSION['user_id'] = $user->getId();
        return true;
    }
    return false;
}

function logout()
{
    session_destroy();
}

function isLoggedIn()
{
    return isset($_SESSION['user_id']);
}

function generateFormHash($salt)
{
    $hash = md5(mt_rand(1,1000000) . $salt);
    $_SESSION['csrf_hash'] = $hash
    return $hash;
}

function isValidFormHash($hash)
{
    return $_SESSION['csrf_hash'] === $hash;
}

编辑:我误解了原来的问题。我在上面添加了用于生成和验证表单哈希的相关方法;

请参阅以下资源:

于 2010-01-09T17:55:54.210 回答
0

您可以查看 zend 框架实现。

除了具体的实现之外,文档还描述了这种元素在表单上的推理和用法。

它的 Zend_Form_Element_Hash https://docs.zendframework.com/zend-form/element/csrf/

于 2010-01-09T18:06:08.253 回答