繁体   English   中英

如何在 PHP (Laravel) 中验证请求的源域

[英]How to verify the origin domain of a request in PHP (Laravel)

我正在开发一个 Laravel 应用程序,我正在为其他网站构建一些 API。 但我试图让我的 API 的实现尽可能简单。 我的期望是用户只会在 HTML 头中使用这个标签:

<script src="api.mydomain.com">

Now I have a controller on this URL that provides the source javascript with the content-type header, but before it goes there, the router will first execute my authentication middleware. 假设它看起来像这样:

public static $users = [
    'client1.com',
    'client2.com',
    'client3.com'
];

public function handle(Request $request, Closure $next)
{
    $origin = "HERE I NEED THE ORIGIN URL"; // e.g. client4.com

    if ( !in_array($origin, self::$users) ) {

        abort(401);

    }

    return $next($request);
}

从代码中可以看出,我需要检索$origin变量。 因此,如果网站client1.com将尝试插入我的javascript ,它将成功获得 javascript 代码。 如果client4.com尝试访问它,则会收到 401 错误。

我发现了$_SERVER['HTTP_REFERER']或 Laravel 的$request->server('HTTP_REFERER') 的方法,但是这些数据可能是伪造的,对吧?

在最好的情况下,我想检索原始域,当不可用时(例如,来自私有 cURL 请求),我想获取 IP 地址。 当然,我需要它是安全的——clients1/2/3 为我的 API 付费,其他人没有。

我该怎么做? 或者有没有更好的原产地认证方法?

所有引用的东西都可以被欺骗。

付费 API 的最佳方式是发出 API 呼叫密钥。

您的 API 可以显示结果或错误,具体取决于客户端是否具有正确的 API 密钥并已付费。

您还应该保留带有时间戳和 clientID 以及 IP 地址的 API 调用的日志表。 因此,您可以不时从通话频率和 IP 模式中检查您的付费客户是否与其他人共享他的密钥。

不时清理此日志表以保持其小而高效。

所以我通过在中间件处理程序中添加标题(感谢@jewishmoses 的灵感)来解决这个问题。 我的 Javascript 基本上对每个人都可用,但它只提供一个按钮,试图创建一个内部包含 iframe 的新元素(我的应用程序也可用作 API)。

假设我在服务器上有一个关联数组,我可以从任何数据库动态填充:

$clients = [
    'client1' => 'paying-customer.com',
    'client2' => 'also-paying-customer.com',
];

...我的 API 路线定义为“ api.mydomain.com/{client} ”和“ api.mydomain.com/{client}/iframe 该处理程序负责添加标头:

public function handle(Request $request, Closure $next)
{
    $client = $request->route('client',null);

    $clientSet = $client !== null;
    $clientAccepted = isset($clients[$client]);

    if ( $clientSet and !$clientAccepted ) {

        abort(401);

    }

    $response = $next($request);


    if( $clientSet and isset($response->headers) and $response->headers instanceof ResponseHeaderBag){

        $clientDomain = $clients[$client];

        $response->headers->add([
            'Content-Security-Policy' => "frame-ancestors https://*.$clientDomain/ https://$clientDomain/"
        ]);
    }



    return $response;
}

现在可能会发生什么:

  1. client1 成功从api.mydomain.com/client1导入 javascript ,它将尝试访问api.mydomain.com/client1/iframe (也成功)
  2. client3 尝试从api.mydomain.com/client3导入 javascript 失败
  3. client3 成功从api.mydomain.com/client1导入 javascript ,它将尝试访问api.mydomain.com/client1/iframe (被 headers 拒绝)

也许有一种更优雅的方法来阻止加载 javascript,但是在我看来,提供我自己的应用程序作为 API(在 iframe 中)是足够安全的,因为我可以控制谁可以使用它,现代浏览器将帮助我阻止“小偷” ”。 资源对解决我的问题最有帮助。

暂无
暂无

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

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