使用session禁用来自网站外部的帖子请求(php安全性)

时间:2016-07-22 08:11:39

标签: php security

我希望禁用从其他网址或软件发送的帖子请求(CSRF攻击) 并注意:(我不想为我的表单设置csrf令牌输入

如果我在用户登录后在会话中设置了csrf令牌,则接受

? 感谢

1 个答案:

答案 0 :(得分:0)

如果你想避免使用CRSF,你就没有什么好的选择。 $_SERVER['HTTP_REFERER']变量通常是设置的,通常对应于请求来自的网站,因此您可以使用它来阻止某些外部请求。但是,与来自浏览器的所有数据一样,如果没有验证,您将无法信任它,因此不应将其视为安全。 The docs say

  

这是由用户代理设置的。并非所有用户代理都会设置此项,并且   有些提供了将HTTP_REFERER修改为功能的功能。在   简而言之,它无法真正被信任。

CSRF检查是防止外国域名发出请求的最佳选择。如果您不想,您不必将其作为输入包含在表单中;你可以改用cookies和标题:

1. 当用户登录时,使用PHP的setcookie将令牌存储在Cookie中。在用户会话中存储匹配的令牌以及到期日期

$token = '...'; //<- look up how to generate a good random token
$expire = time()+1800; //expire in 30 minutes
setcookie("XSRF-TOKEN", $token, $expire);  /* expire in 1 hour */
$_SESSION['XSRF-TOKEN'] = ['token'=>$token, 'exp'=>$expire];

2。当您的网站发出请求时,请使用Javascript从document.cookie读取令牌,并将下面的标题设置为完全相同的值:

X-XSRF-TOKEN: 43b7acd76d6....

如果您担心必须更新大型网站,这是您最好的选择。您可以指示浏览器在发出HTTP请求时运行Javascript函数。此函数可以读取cookie并设置标题。许多框架都会为您完成此任务,但对于vanilla JS,请查看this resource

3. 每当您的PHP脚本收到请求时,首先查找此标头的值,然后将其与您在用户会话中保存的值进行比较。记得检查过期!

$request_token = apache_request_headers()['X-XSRF-TOKEN']? : null;
$session_token = $_SESSION['XSRF-TOKEN'];
if($request_token===null) die('Token is missing');
if($session_token['exp'] < time()) die('Token has expired');
if($session_token['token']!==$request_token) die('Token is invalid');
//safe to continue. Repeat step 1 to set a fresh token

只有可以读取XSRF-TOKEN cookie的域才知道要在标头中设置什么值。由于浏览器不允许一个域从另一个域读取cookie,因此该机制将保护您免受不良来源的请求。并且它会根据您的要求将csrf位保留在表单之外。