简体   繁体   English

仅接受来自特定页面的AJAX $ _GET或$ _POST请求

[英]Only accept AJAX $_GET or $_POST requests from specific page

Is it possible to check that the $_GET or $_POST values are submitted from specific page? 是否可以检查是否从特定页面提交了$_GET$_POST值?

For example, there is an ajax in page1 submitted value to page2.php?q=abc , and the page2 only accept the q when it is submitted from page1 . 例如, page1提交的值中的ajaxpage2.php?q=abc ,而page2仅在从page1提交时接受q

If I directly browse to the page page2.php?q=abc , the php will not run unless I submitted the value from page1 . 如果我直接浏览到page2.php?q=abc页面,除非我从page1提交了值,否则php不会运行。

Is it possible to do that? 有可能吗?

Edit 1: 编辑1:

Because I can access the page2 and get the result. 因为我可以访问page2并获得结果。 Don't mention about the session , because I can validate the session to match my needs and the values submitted to php is valid or not. 不要提及session ,因为我可以验证session以满足我的需求,提交给php的值是否有效。

What I want is to check if the request is sent from specific page or not. 我想要的是检查请求是否从特定页面发送。 If true, then accept the values and process it, else, redirect to homepage or something else. 如果为true,则接受值并处理它,否则,重定向到主页或其他内容。

Edit 2: My question is, not only values submitted through Ajax, but also direct access, such as href="page2.php?q=abc" . 编辑2:我的问题是,不仅是通过Ajax提交的值,还有直接访问,例如href="page2.php?q=abc" I guess token will be the best way to do that, and the query part will validate again. 我想令牌将是最好的方法,查询部分将再次验证。

There are two security checks you could perform while dealing with AJAX: 在处理AJAX时,您可以执行两项安全检查:

1) Check if the request it sent through AJAX: 1)检查它是否通过AJAX发送的请求:

if ( !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' )
{
       //AJAX Request Detected
}

2) Hashed tokens: 2)散列令牌:

On the page that's holding the AJAX Request, create a token: 在持有AJAX请求的页面上,创建一个令牌:

session_start();
$hashed='';
$_SESSION['token'] = microtime(); 
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
    $salt = '$2y$11$' . substr(md5(uniqid(mt_rand(), true)), 0, 22);
    $hashed = crypt($_SESSION['token'], $salt);
}

This is using the blowfish algorithm with the crypt() to create hashed string. 这是使用带有crypt()blowfish算法来创建散列字符串。

Your AJAX function would be like: 你的AJAX函数就像:

$.ajax({
    type: "POST",
    url: 'page2.php',
    data: {
        action: '<?php echo $hashed;?>', //pasted the hashed string created in PHP
        q: 'test'
    },
    success: function (data) {}
});

Upto you whether you want to use $_GET or $_POST method. 无论你是否想要使用$_GET$_POST方法。

And then on the second page which is receiving the AJAX request, you do: 然后在接收AJAX请求的第二页上,您执行以下操作:

session_start();
if(crypt($_SESSION['token'], $_POST['action']) == $_POST['action']){
   //Hashed string matches. Request has come from page1.
   echo $_POST['q'];
}

in your form you can just add a hidden field and add a page id. 在您的表单中,您只需添加隐藏字段并添加页面ID。 On the page that should send post or get request you can do something like 在应发送帖子或获取请求的页面上,您可以执行类似的操作

<form action='phpscript.php'>
    <input type='hidden' name='page' value='valid_page'>
    <input name='your_other_info'>
</form>

In the phpscript.php you can do something like 在phpscript.php中你可以做类似的事情

<?php
    //If you have a request, it can be either post or get method
    if(isset($_SERVER['REQUEST_METHOD']) && (isset($_POST['page']) || isset($_GET['page']))){

    }else{
        //Post or get is not from the valid page
    }
?>

You cannot restrict the "origin" of the request, because there's no such thing per se. 你不能限制请求的“起源”,因为本身没有这样的东西。 Your "page" isn't sending a request, it's the browser that does it. 您的“页面”不是发送请求,而是执行此操作的浏览器。 And the browser may have any number of reasons why it's sending you a request; 浏览器可能有多种原因可以向您发送请求; be that because one of your pages has instructed it to do so or because a user is fiddling around with the Javascript console manually. 因为你的一个页面已经指示它这样做,或者因为用户正在手动摆弄Javascript控制台。

All you get on your end is an HTTP request. 你得到的只是一个HTTP请求。 Go ahead, inspect it. 来吧,检查一下。 In the browser, look at the network tab and inspect the raw request being sent. 在浏览器中,查看网络选项卡并检查正在发送的原始请求。 It's just a bunch of HTTP headers, nothing more. 它只是一堆HTTP标头,仅此而已。 Anyone can send an HTTP request with arbitrary HTTP headers any time from anywhere and make it look like anything they want. 任何人都可以随时随地发送带有任意HTTP标头的HTTP请求,并使其看起来像他们想要的任何内容。 Even the Referer HTTP header is not going to "protect" you. 即使是Referer HTTP标头也不会“保护”你。

If you need any sort of protection, you can use session tokens or user authentication to restrict the set of potential entities that can send queries somewhat. 如果您需要任何类型的保护,可以使用会话令牌或用户身份验证来限制可以稍微发送查询的潜在实体集。 But what you have is still by definition a public URL endpoint which answers to arbitrary HTTP queries. 但是你所拥有的仍然是一个公共URL端点,它可以回答任意HTTP查询。 You cannot restrict their "origin page". 您不能限制他们的“原始页面”。 The best you can do is obfuscate it by requiring certain headers to be set (like Referer or X-Requested-With). 您可以做的最好的事情是通过要求设置某些标头来对其进行模糊处理(如Referer或X-Requested-With)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM