PHP 表单令牌的使用和处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2034281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 04:44:38  来源:igfitidea点击:

PHP form token usage and handling

phpformslogintoken

提问by dave

I'm a beginner working on a login script in PHP. This is the form token statement that I have so far:

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

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

The statement is issued just after the user indicates that he/she wants to login.

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

My limited understanding is that the tokens purpose is to identify a unique user at a unique point in time and to disguise the form token information.

我有限的理解是令牌的目的是在唯一的时间点识别唯一的用户并伪装形式令牌信息。

Then everything becomes fuzzy. Here are my 3 open questions:

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

  1. When is the best time to "check" the form token for security purposes?

  2. How do I check it?

  3. When, if ever, do I "destroy" the form token? (IOW, would the form token stay "active" until the user logs out?

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

  2. 我该如何检查?

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

采纳答案by hobodave

There is no need to do what you are attempting. When you start a session in PHP with session_start() a unique SESSIONID is already generated for you. You should notbe putting this on the form. It is handled via cookies by default. There is also no need to check the SESSIONID either, that again is handled for you.

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

You are responsible for authenticating the user and storing their authenticated identity (e.g. $_SESSION['user_id'] = $userId in the SESSION. If a user logs out you destroy their session with session_destroy.

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

You should ensure session_start() is one of the firstthings for all pages in your site.

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

Here is a basic example:

这是一个基本示例:

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

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;
}

Edit: I misunderstood the original question. I added the relevant methods above for generating and validating form hashes;

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

Please see the following resources:

请查看以下资源:

回答by jspcal

this is to prevent CSRF attacks

这是为了防止 CSRF 攻击

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

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

a malicious site could theoretically display a form that posts to your application. the form might contain instructions that cause a data breach or some unwanted action. the user might be deceived into submitting the form which the app would accept because the user is already logged in. a form token ensures the form was created by your site and not some other site.

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

checking the HTTP_REFERER is often good enough, but not as complete a solution (https for instance won't send the referrer string).

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

if you really want to secure all forms with a token, you can create some convenience functions like emitToken() and checkToken() that will make it work site-wide.

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

some examples:

一些例子:

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

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

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

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

回答by txyoji

You could check out the zend framework implementation.

您可以查看 Zend 框架实现。

Apart from the specific implementation, the docs describe the reasoning and usage of this kind of element on a form.

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

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

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