在 PHP 中检测 Ajax 并确保请求来自我自己的网站
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1953954/
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
Detecting Ajax in PHP and making sure request was from my own website
提问by Yossi
I use my PHP back-end to detect AJAX requests by checking for a value in $_SERVER['HTTP_X_REQUESTED_WITH'].
我使用我的 PHP 后端通过检查$_SERVER['HTTP_X_REQUESTED_WITH'].
This gives me a reliable detection, making sure the request is made utilizing AJAX techniques.
这为我提供了可靠的检测,确保使用 AJAX 技术发出请求。
How can I make sure the request came from my own domain, and not an external domain/robot?
如何确保请求来自我自己的域,而不是外部域/机器人?
www.example.com/ajax?true could allow anyone to make an AJAX call and cut the information.
www.example.com/ajax?true 可以允许任何人进行 AJAX 调用并切断信息。
I could make sessions for everyone that enters my website normally, and then allow AJAX calls.. but that can be faked too.
我可以为正常进入我网站的每个人创建会话,然后允许 AJAX 调用......但这也可以伪造。
Does it even matter these days?
这些天还重要吗?
采纳答案by Gordon
Let you Controller
让你控制器
- generate access token
- store in session for later comparison
- 生成访问令牌
- 存储在会话中供以后比较
In your View
在你看来
- declare the access token as JS variable
- send the token with each request
- 将访问令牌声明为 JS 变量
- 随每个请求发送令牌
Back in your Controller
回到你的控制器
- validate HTTP_X_REQUESTED_WITH
- validate token
- 验证 HTTP_X_REQUESTED_WITH
- 验证令牌
Check these security guidelines from OpenAjax.
Also, read the article on codinghorror.com Annie linked.
从 OpenAjax查看这些安全指南。
另外,请阅读有关 Codinghorror.com Annie 链接的文章。
回答by Annie
You can check the HTTP_REFERRER, but not all browsers set it. The best way is to write a wrapper for your ajax calls on the JavaScript side which sends part of document.cookie back to the server--only your domain has access to the cookie. You can compare the cookie in the request headers with the cookie in the AJAX call in php.
您可以检查 HTTP_REFERRER,但并非所有浏览器都会设置它。最好的方法是在 JavaScript 端为您的 ajax 调用编写一个包装器,它将 document.cookie 的一部分发送回服务器——只有您的域可以访问 cookie。您可以将请求标头中的 cookie 与 php 中 AJAX 调用中的 cookie 进行比较。
In response to, "does it even matter, these days"--YES, it does! Read this.
作为回应,“这些天它甚至重要吗”--是的,它确实重要!读这个。
回答by Jim
Regarding your last question: "Does it even matter, in these days?" This is a case by case question. If the ajax request is doing something that does not require security (e.g. loading latest stock quotes) then it really doesn't matter IMHO. If the request is loading information that should be secured (e.g. returning identifying information or doing something on the server) then you should treat it as such.
关于你的最后一个问题:“在这些日子里,这还重要吗?” 这是个案问题。如果 ajax 请求正在做一些不需要安全性的事情(例如加载最新的股票报价),那么恕我直言,这真的无关紧要。如果请求正在加载应该受到保护的信息(例如返回识别信息或在服务器上做某事),那么您应该这样对待它。
I personally don't use the server variables to know when something is an ajax request. Instead I just add a query parameter to the ajax call (e.g. http://domain.com/?ajax=true). If I need to secure the ajax call then I would use the same methods as securing a regular page request (using both client and server). As Lucas Oman pointed out, anything on the client side can be faked. Bottom line don't trust any request even if you think it is coming from your site or database. Always follow the mantra "filter input - escape output".
我个人不使用服务器变量来知道什么时候是 ajax 请求。相反,我只是向 ajax 调用添加了一个查询参数(例如http://domain.com/?ajax=true)。如果我需要保护 ajax 调用,那么我将使用与保护常规页面请求相同的方法(使用客户端和服务器)。正如 Lucas Oman 所指出的,客户端的任何东西都可以伪造。底线不要相信任何请求,即使您认为它来自您的站点或数据库。始终遵循“过滤输入 - 转义输出”的口头禅。
回答by Ben Shelock
David Walsh has a good solution
大卫沃尔什有一个很好的解决方案
/* 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.... */
回答by Lucas Oman
Really, the most secure way to do this is to, as you suggested, use server-side sessions, as these cannot be crafted as cookies can.
确实,最安全的方法是按照您的建议使用服务器端会话,因为它们不能像 cookie 那样制作。
Granted, someone can still hiHyman a session ID, but if you also store the user's IP address in their session and check it on each request, you can weed out a lot of hiHymans. Only someone on the same LAN or proxy could hiHyman it.
诚然,有人仍然可以劫持会话 ID,但如果您还将用户的 IP 地址存储在他们的会话中并在每次请求时检查它,您就可以清除很多劫持。只有在同一 LAN 或代理上的人才能劫持它。
Any other method mentioned--cookies, javascript, http referer--depends on client-side data, which is insecure and should always be suspected of being fake, forged, hiHymaned and maliciously constructed.
提到的任何其他方法——cookies、javascript、http referer——都依赖于客户端数据,这是不安全的,应该始终怀疑是伪造、伪造、劫持和恶意构建的。
回答by v4d
Use POST session secured requests:
使用 POST 会话安全请求:
Inside the Webpage (e.g. index.php) we need to store the sessionid
在网页(例如 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>
The ajax requests (ajaxrequest.js)
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' ];
});
Responsible php side:
负责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 ) );
}
回答by Sampson
Check the $_SERVER['HTTP_REFERER']. This will work in many cases, but shouldn't be confused for a completely-secure solution.
检查$_SERVER['HTTP_REFERER']. 这在许多情况下都有效,但不应与完全安全的解决方案混淆。

