如何在php中获取http请求来源

Posted

技术标签:

【中文标题】如何在php中获取http请求来源【英文标题】:How to get http request origin in php 【发布时间】:2014-10-20 14:54:01 【问题描述】:

我想创建一个 API,并且为了验证 API 消费者,我将提供一个 API KEY、App-id 和 App-Secret。问题是我想知道http请求来自哪里,这样我就可以知道发出que请求的主机是否是注册主机。例如:www.someone.com 有一个 app-id :0001、app-secret:1200 和 api-key:458。如果这个凭证用于发出A请求,我想知道请求者是否真的是www.someone.com

【问题讨论】:

对于来源使用这个header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN'] . "");,然后从 GET 或 POST 变量中检查凭据 使用来源作为安全措施是无用的。这个头可以很容易地be faked。相反,您可能希望使用回调来传递一些“请求令牌”(想想 oauth 流程是如何工作的)。 使用 HTTP_ORIGIN 或 HTTP_REFERER 而不检查它们“本质上”与使用“*”相同,这可能会打开微妙的安全漏洞,因此不鼓励,请参阅 ***.com/questions/12001269/… 实际问题“如何获取http请求来源”的答案可以在这里找到:***.com/questions/41326257/… 【参考方案1】:

从技术上讲,originreferer 都不是必需的 HTTP 标头,所有这些答案都基于发送的特定浏览器标头,并且将您的系统基于客户端的不同行为是一个坏主意。

正确的答案是您无法可靠地获取每个请求的客户端来源,因为它不是 HTTP 规范的一部分。

【讨论】:

【参考方案2】:

在 laravel 7 中这对我有用

request()->headers->get('referer');

【讨论】:

先用request()->headers检查一下;然后你可以添加“->get('..needed parameter..');”【参考方案3】:

Laravel 5:在请求方法控制器中:

$origin = request()->headers->get('origin');

【讨论】:

获取所有标题:request()->headers->all(); 未经授权的人不能简单地更改其客户端中的请求标头以发送授权域的域并以此绕过检查吗? 我刚刚在另一个线程上找到了答案:***.com/a/21058346/4688612 origin 未使用 GET 发送 @mangusta browser add origin header for CORS requests - more here - 如果你不发送 CORS 请求,那么浏览器不会添加这个 header 并且可能 php 也没有设置它(或者可能设置一些默认值 - 但我没有在 php 端检查这个)。【参考方案4】:

一般来说,这个标题应该可以完成这项工作。在此标头中有域名

header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN'] . "");
// use domain name instead of $_SERVER['HTTP_ORIGIN'] above

但如果您想查看更多信息,请使用以下 sn-p 之类的内容

$allowed = array('domain1', 'domain2', 'domain3'); 

if(isset($_SERVER['HTTP_ORIGIN']) && in_array($_SERVER['HTTP_ORIGIN'], $allowed))
    // SELECT credentials for this user account from database
    if(isset($_GET['api_key'], $_GET['app_secret'])
        && $_GET['api_key'] == 'api_key_from_db' 
        && $_GET['app_secret'] == 'app_secret_from_db'
    )
        // all fine
    else
        // not allowed
    
else
    // not allowed

如果用户必须向您的服务传递更多数据,请使用 POST 而不是 GET

【讨论】:

如果 $_SERVER['REMOTE_ADDR'] 变量返回给我的是 Client_IP 而不是网站地址,我应该如何验证网站?? @m_junior $_SERVER['REMOTE_ADDR'] 返回当前脚本正在执行的服务器的IP地址。 @m_junior 上面的$allowed 数组可能看起来像$allowed = array('domain1' => '1.2.3.4', 'domain2' => '5.6.7.8', 'domain3' => '2.4.6.8');,然后您可以使用gethostbyname('domain') 并将返回的主机IP 与您的数组中的IP 进行比较。 @hex494D49 你为什么拒绝我的编辑?您的代码有 4 个语法错误,并且不是针对 SO 的最佳格式。 我不知道一年前我发表评论时发生了什么。重要的是数组$allowed,这使它成为一个很好的答案。【参考方案5】:

使用$_SERVER['HTTP_REFERER']。它是将用户代理引向当前页面的页面地址(如果有)。这是由用户代理设置的。不是所有的用户代理都会设置这个,有些提供修改HTTP_REFERER 的功能。

对于进一步的限制,您可以执行以下操作。 example.com 应更改为您的域。

IIS 在网页配置中设置如下

add name="Access-Control-Allow-Origin" value="http://www.example.com"

Apache在httpd.conf/apache.conf下面设置

Header add Access-Control-Allow-Origin "http://www.example.com"

【讨论】:

referrer 和 origin 是两个不同的东西。 并不是所有的用户代理都会设置这个,有些提供了修改 HTTP_REFERER 的功能。简而言之,它不能真正被信任。 可以在此处找到该问题的更好答案:***.com/questions/41326257/… @DanFromGermany 谈到,ORIGIN 和 REFERER 是两个不同的东西 - 在这种情况下,HTTP_ORIGINHTTP_REFERER 更好;如果缺少HTTP_ORIGIN,那么您可能希望回退到使用HTTP_REFERER,但出于安全考虑,我建议不要这样做(更改引用比更改来源更容易,因为来源被列为“禁止”标题和浏览器应该防止对原点进行任何更改)。【参考方案6】:

我认为您的意思是您想要访问请求标头中的“Origin”标头(而不是在响应标头中设置它)。

为此,最简单的方法是访问内置的 getallheaders() 函数 - 这是 apache_request_headers() 的别名 - N.B.这是假设您使用 php 作为模块。

这将返回一个数组,因此 Origin 标头应该像这样可用:

$request_headers = getallheaders();
$origin = $request_headers['Origin'];

如果您通过 fastcgi 之类的方式使用 php,那么我相信它会在环境中可用 - 通常大写并以“HTTP_”为前缀,因此它应该是 $_SERVER['HTTP_ORIGIN']

希望能帮助其他寻找这个的人:)

【讨论】:

getallheaders();在 php-fpm 或 php-fastcgi 中不存在 是的,这就是为什么我提到假设您使用 php 作为模块 (mod_php),否则它可用作环境变量。【参考方案7】:

使用var_dump,您可以看到request 提供的所有功能。

var_dump($_REQUEST);

也对server 全局执行var_dump。它包含很多有用的信息。

var_dump($_SERVER);

【讨论】:

我在我的前端服务器上使用了这个,但我忘记删除它,服务器被黑了。很多“有用信息”非常危险

以上是关于如何在php中获取http请求来源的主要内容,如果未能解决你的问题,请参考以下文章

请问下 php 怎么获取 ajax 请求 来源页面的 完整 url 地址啊?

图解 nginx 如何获取真实的来源 IP

php模拟post请求,获取不到数据

在 PHP 中检测获取请求

php如何通过get方法发送http请求,并且得到返回的参数

php如何发送带中文的http请求?