php REST-防止在浏览器中直接访问

时间:2018-10-19 11:52:16

标签: php rest .htaccess api

我正在用PHP开发REST API服务器,我打算通过客户端应用程序调用它,但是我想防止通过浏览器直接访问API。

例如说我对“ HOST / api / article / id”进行了GET调用,它将给定ID的文章返回给客户端应用程序。但是,当我在浏览器中键入“ HOST / api / article / id”时,不应返回该文章-我什么也不想发生(例如,只返回空页或403)。

  • 这可能吗?
  • 如果是的话,这是常见的做法吗?(我的意思是这是人们通常会想要做的事情,还是它晦涩难懂和/或违反了HTTP / REST原则,应该避免吗?)
  • 如果是,该怎么办?(在PHP / .htaccess / etc中)

我知道我可以实现某种授权(例如API密钥)来代替,该授权将只允许我打算执行的客户端应用程序执行API。

(我对此很陌生,所以也许我的问题没有道理。也许我误解了有关REST / HTTP /无论如何工作的一些基本知识。如果可以,请告诉我。)

1 个答案:

答案 0 :(得分:1)

通常的方法是:

  1. 您的客户端(使用公共密钥),从服务器请求令牌,令牌检查密钥是否有效且未列入黑名单(如果旧密钥被泄露,您可以将其过期/将其列入黑名单)
  2. 每次发送令牌
  3. 服务器仅在令牌存在时响应

根据您的要求,可以采用一种简便的方法来实现此目的。

  1. 具有一个名为“ my_client”的变量,其值为true
  2. 在应用程序发出的每个请求中,都会在标头中发送变量。
  3. 如果标头中包含“ my_client”变量,则服务器仅服务器信息

此方法的缺点是,这并不是真正安全的方法,因为每个人都可以看到他们提出的请求。因此可以注意到这些额外信息。

它是如此简单,您只需编写一分钟就可以将其作为测试。

<?php
 if(!$_SERVER['HTTP_MY_CLIENT']){
   header("HTTP/1.1 403 FORBIDEN");
  }

在扩展使用标头变量的概念时,我们可以将其用作“半令牌”,这意味着我们将用一个只能读取的随机值填充该值。

所以这个概念是这样的:

客户->请求随机值 客户/设置每个请求标头中的值/ 客户端->向服务器发出请求。

<?php
 /* A basic API token and authentication class. */
 class SimpleToken
 {
    /* Creates a salt based on the passed key that is good for the current day */
   public static function generateSalt($key)
   {
    return md5($key . date('Y-m-d'));
   }
  /* Crytographically combine the key and the salt to produce a token */
   public static function generateToken($key, $content)
   {
    $package = $content . $key;
    return crypt($package);
   }
   /* Generate a relatively strong SSL key */
  public static function generateKey()
   {
    $config = array(
        "digest_alg" => "sha512",
        "private_key_bits" => 4096,
        "private_key_type" => OPENSSL_KEYTYPE_RSA,
    );
    //Create a private key
    $res = openssl_pkey_new($config);
    //Extract the private part of the key
    openssl_pkey_export($res, $private_key);
    //Shorten it up for use in an API
    return md5($private_key);
}

/* Verify the authenticity of the passed key/token pair */
public static function isAuthentic($key, $content, $token)
{
    $package = $content . $key;
    if(crypt($package, $token) == $token)
    {
        return true;
    }
    else
    {
        return false;
    }
  }
}