【发布时间】:2018-02-10 22:44:48
【问题描述】:
我正在尝试在一个应用中实施针对 CSRF 的保护。
在 PHP 中实现起来相对简单。我有很多关于如何使用 Extjs 做到这一点的问题。
我阅读的 EXTJS 书籍没有解决这个主题,我在互联网上找不到关于这个主题的具体指导 - 使用 EXTJS。
一些问题:
使用PHP,将令牌发送到EXTJS?
我是否必须像在 PHP 中一样在每个表单中创建一个隐藏字段?
我是否必须将 Ext.Ajax.requestt 中的令牌发送到服务器端?如何做到这一点?
一些非常简单的代码作为起点:
类令牌:https://www.youtube.com/watch?v=VflbINBabc4
<?php
class Token {
public static function generate() {
$_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32));
}
public static function check($token) {
if(isset($_SESSION['token']) && $token === $_SESSION['token']){
unset($_SESSION['token']);
return true;
}
return false;
}
}
?>
查询
<?php
require('conect.php');
require_once('token.php');
$action = $_REQUEST['action'];
switch($action){
case "create":{
$records = $_POST['records'];
$data = json_decode(stripslashes($records));
if(isset($_POST['cars'], $_POST['token'])){
$cars = $data->{'cars'};
if(Token::check($_POST['token'])){
$sqlQuery = "INSERT INTO the_cars (cars) VALUES (?)";
if($statement = $con->prepare($sqlQuery)){
$statement->bind_param("s", $cars);
$statement->execute();
$success= true;
}else{
$erro = $con->error;
$success = false;
}
}else{
//error
}
echo json_encode(array(
"success" => $sucess,
'errors'=> $erro
));
$statement->close();
$conexao->close();
break;
}
}
?>
如果您能以上面的代码为例,详细了解如何实施此类保护,我将不胜感激。
提前致谢。
一些有用的帖子:
CSRF prevention for AJAX call from extjs to Struts action
How to implement CSRFGuard in ExtJs AjaxRequest?
ExtJS Store SYNC with Spring Security ON
http://blog.gugl.org/archives/category/extjs
已编辑
我喜欢的一种可能性是在每个 Ajax 请求上发送令牌:https://www.sencha.com/forum/showthread.php?134125
Aplication.js 中的 Mabe。文件
init: function () {
Ext.require(["Ext.util.Cookies", "Ext.Ajax"], function(){
// Add csrf token to every ajax request
var token = Ext.util.Cookies.get('csrftoken');
if(!token){
Ext.Error.raise("Missing csrftoken cookie");
} else {
Ext.Ajax.defaultHeaders = Ext.apply(Ext.Ajax.defaultHeaders || {}, {
'X-CSRFToken': token
});
}
});
}
OR 来自 使用 EXT JS 构建应用程序视频由 PACKT 发布,但节点在服务器端
var csrfToken = Ext.query('meta[name=csrf-token]')[0].getAttribute('content');
Ext.Ajax.defaultHeaders = ('X-CSRF-Token': csrfToken);
Ext.Ajax.extraParams = {'csrf': csrfToken};
我仍然对如何正确地将服务器端(生成令牌并进行相应的检查)与客户端相关联存有疑问。
已编辑
在过去的几天里,我多次尝试使用 php 和 EXTJS 运行 CSRFProtector。
通过进行的分析,我能够使用 Chrome 开发工具验证以下内容:
如果只是在我添加的文件索引的开头(而不是在其他 php 文件中):
include_once __DIR__ .'csrfp/libs/csrf/csrfprotector.php';
csrfProtector::init()
我开始使用 Chrome 开发工具:
csrfprotector.js 文件已加载
在我加载的 php 文件中 » 方法:POST,Status 200,Type xhr,Initiator csrfprotector.js:259
我看到数据(JSON 格式)和一个令牌已发送,并且请求标头作为具有相同令牌的 Cookie
在 index.php 文件中,如预期的那样,另外创建了以下内容:
(...)
<script type="text/javascript"
src="http://my_path/csrfp/js/csrfprotector.js"></script>
<script type="text/javascript">
window.onload = function() {
csrfprotector_init();
};
</script>
</body>
</html>
不返回错误
当我在 php 文件(包含将接收请求数据的查询,例如创建记录)的开头添加 include_one 和 csrfProtector::init() 请求时,成功为 false我得到一个状态码 403 和消息 403 CSRFProtector 禁止访问!
如果我在 csrfProtector::init (); 之前添加一个 echo 'Test 1',和一个 echo 'Test 2' 之后,只是第一个 echo 有效。所以这在我的 php 代码中不是问题,而是在使用 csrfprotector 进行验证时。
在开发工具中,您会看到错误 403 是通过提及以下脚本行触发的:csrfprotector: 259。 该文件的第 259 行是:return this.old_send (data);
我将探讨 csrfprotector 可能与 JSON 不兼容的情况。
如果我们能够使用 PHP 和 EXTJS(使用 JSON)运行 CSRFProtector,这将是一个可以为许多人带来不同的解决方案,因为它很容易实现。
服务器端接收到的数据格式示例:
Array
(
[action] => create
[_dc] => 1505398990654
[data] => {"id_cars":"id_1","cars":"test"},
)
【问题讨论】:
-
更新了我的答案以展示如何使用 ExtJS 中的 CSRF-Protector
-
感谢 Micael 的宝贵帮助,并坚持帮助我们找到 CSRFProtector 的解决方案。我用一些可以帮助识别问题的数据编辑了我的小提琴。
-
我确定 Protector 无法验证 JSON 请求(如我的回答中所述) - 发送 JSON 是状态码 403 的原因。您可以切换到
Content-type: application/x-www-form-urlencoded(链接 Sencha Fiddle 中的示例)或打开问题\帮助来修复保护器以使其与 json 一起使用。目前没有其他办法...... -
感谢 Michal 的澄清和出色的帮助。
-
不客气。通过这样做,我学到了很多东西;)
标签: javascript php extjs extjs5 csrf-protection