在PHP中检测Ajax并确保请求来自我自己的网站

我使用我的PHP后端通过检查$_SERVER['HTTP_X_REQUESTED_WITH']的值来检测AJAX请求。

这给了我一个可靠的检测,确保请求是利用AJAX技术。

我怎样才能确保请求来自我自己的域名,而不是一个外部的域名/机器人?

www.example.com/ajax?true可以允许任何人进行AJAX呼叫并切断信息。

我可以为通常进入我的网站的每个人创build会话,然后允许AJAX调用..但是这也可能是假的。

这些日子甚至不重要吗?

让你控制器

  • 生成访问令牌
  • 存储在会话中以供稍后比较

在你的视图

  • 将访问令牌声明为JSvariables
  • 每个请求发送令牌

回到你的控制器

  • validationHTTP_X_REQUESTED_WITH
  • validation令牌

从OpenAjax检查这些安全指导原则 。
另外,请阅读有关codinghorror.com Annie的文章。

你可以检查HTTP_REFERRER,但不是所有的浏览器都设置它。 最好的方法是在JavaScript端发送ajax调用的包装,将document.cookie的一部分发送回服务器 – 只有你的域可以访问cookie。 您可以将请求头中的cookie与php中的AJAX调用中的cookie进行比较。

为了回应,“最近这件事情是否重要” – 是的,它的确如此! 阅读这个 。

关于你的最后一个问题:“在这些日子里,这事关系重大吗?” 这是一个个案的问题。 如果ajax请求正在做一些不需要安全性的事情(例如,加载最新的股票报价),那么它真的没关系恕我直言。 如果请求正在加载应该被保护的信息(例如返回标识信息或者在服务器上做某事),那么你应该这样对待它。

我个人不使用服务器variables来知道何时是一个Ajax请求。 相反,我只是添加一个查询参数到ajax调用(例如http://domain.com/?ajax=true )。 如果我需要保护ajax调用,那么我将使用与保护常规页面请求(使用客户端和服务器)相同的方法。 正如卢卡斯·阿曼(Lucas Oman)指出的那样,客户端上的任何东西都可能是假的。 底线不相信任何请求,即使你认为它来自您的网站或数据库。 始终遵循口头禅“filterinput – 退出输出”。

大卫·沃尔什有一个很好的解决scheme

 /* decide what the content should be up here .... */ $content = get_content(); //generic function; /* AJAX check */ if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { /* special ajax here */ die($content); } /* not ajax, do more.... */ 

真的,最安全的方法就是按照你的build议使用服务器端会话,因为这些会话不能像Cookie那样制作。

诚然,某人仍然可以劫持会话ID,但是如果您还将用户的IP地址存储在会话中,并在每个请求上进行检查,则可以清除很多劫持。 只有在同一局域网或代理上的人才能劫持它。

任何其他提到的方法 – cookies,javascript,http referer – 取决于客户端的数据,这是不安全的,应该总是怀疑是伪造,伪造,劫持和恶意构build。

使用POST会话安全的请求:

在网页里面(比如index.php),我们需要存储sessionid

 <?php // Create Session $session = session_id(); if(empty($session)) session_start(); ?> <head> ... <script type="text/javascript"> sid = '<?php echo session_id(); ?>'; </script> <script type="text/javascript" src="ajaxrequest.js"></script> ... </head> 

ajax请求(ajaxrequest.js)

 /* simple getAjax function * @param $url request url * @param $param parameter (dont use ?) * @param callback function on success */ var spinnerid = '#spinner'; // Spinner as long ajax requests running $(document).ajaxStart(function() { $(spinnerid).show(); }); $(document).ajaxStop(function() { $(spinnerid).hide(); }); function getAjax( url, param, callback ) { var data = null; url += "?sid=" + sid + "&" + param; $.ajax({ url: url, method: "POST", // uncomment to use GET, POST is secured by session cache: false, async: true, success : function(data){ callback(data); }, } getAjax( 'http://domain.com/', 'data=foo', function( data ) { // do stuf with data var jsonobj = eval("(" + data + ")"); var data = jsonobj[0][ 'data' ]; }); 

负责任的PHP方面:

 if( isset( $_GET['sid'] ) ) $client_sid = $_GET['sid']; if( session_id() == null ) session_start(); if( session_id() != $client_sid ) { // noID or wrongID, redirect to mainindex ignore_user_abort(true); header( "HTTP/1.1 403 Forbidden" ); header("Connection: close", true); exit; } else { // get data if( isset( $_GET['data'] ) ) { $data = $_GET['data']; } else if( isset( $_POST['data'] ) ) { $data = $_POST['data']; } else { $data = null; } // do stuff with data // return data as json $resp[0]['data'] = $data; print_r( json_encode( $resp ) ); } 

检查$_SERVER['HTTP_REFERER'] 。 这在很多情况下都可以工作,但是不应该把它搞糊涂成一个完全安全的解决scheme。