我已经创建了一个API,它接受hostkey或API_KEY,然后它验证并返回JWT令牌。一切正常,没有Hostkey我无法访问受限路由。
主要的问题是,如果有人把这个主机密钥给别人会发生什么,因为它将不再受到保护或它将被滥用。因此,我要做的不仅是验证主机密钥,还要验证请求来自的域。这是一种付费服务,我想把它限制在特定的领域。就像google使用MAP Api一样,如果我们将MAP键添加到其他域,它会抛出错误。
要做到这一点,唯一的方法是检查源和引用头。
不幸的是,服务器到服务器这不能可靠地完成,因为referrer和origin标头将由编码器设置,因此很容易被欺骗。对于服务器到服务器的调用,最好将允许调用api的IP地址列入白名单。在这种情况下,使用类似于"如何从访问者获得真实IP ?"获取服务器的真实IP,并对照白名单IP进行验证。
假设这是浏览器中的JS调用,而不是服务器对服务器的调用,并且您信任浏览器,那么真正可以做到这一点的唯一方法是验证referrer和origin标头。这仍然可以被浏览器插件甚至像Postman这样的工具欺骗,所以我不建议使用高安全性。下面是一个验证源或引用者的PHP示例。
$origin_url = $_SERVER['HTTP_ORIGIN'] ?? $_SERVER['HTTP_REFERER'];
$allowed_origins = ['example.com', 'gagh.biz']; // replace with query for domains.
$request_host = parse_url($origin_url, PHP_URL_HOST);
$host_domain = implode('.', array_slice(explode('.', $request_host), -2));
if (! in_array($host_domain, $allowed_origins, false)) {
header('HTTP/1.0 403 Forbidden');
die('You are not allowed to access this.');
}
CORS头也是可选的,正如@ADyson用PHP头跨域请求头(CORS)所评论的那样
我想建议对请求的数量进行报价或限制,因此当付费API达到100个请求时,密钥将停止工作,然后付费的人将不会为其他人提供密钥。这不是完美的解决方案,但我建议这样做,因为大多数API服务都使用它。