如何控制哪些外部网站访问我的web服务


How can I controll what external web site accesses my web service?

*我正在努力了解如何实现"最简单"的身份识别形式,以便我的合作伙伴网站访问我的web服务来检索信息*

我想确保只有我的合作伙伴有权检索这些信息。没有敏感数据,因为这些数据将显示在我的合作伙伴网站上。但我不希望其他网站利用我的网络服务,在没有访问权限的情况下检索数据

我知道我可以使用HttpRequest对象获取IP地址,然后进行反向查找。但并非所有网站都有专用的ip地址,ISP可能会对多个网站使用相同的ip地址。

我看不出在URL中传递唯一标识符作为参数有什么帮助,因为"任何人"都可以捕捉到这些数据并自己使用。但我会把它当作一张额外的支票。

因此,我想出的唯一"安全"的方法是识别访问我网站的网站,然后根据我服务器上的列表控制它。

我希望您能反馈哪些方法是"最安全的"。

使用公钥/私钥对API请求进行身份验证是web服务中的常见做法。使用它们的几个示例网站:谷歌、推特、EventBrite、Last.FM、GitHub等

这些工作是通过拥有一个众所周知的公钥或消费者密钥。然后为每个用户提供一个私钥或秘密密钥以进行身份验证。使用它最酷的地方是,因为你确切地知道谁在发出请求,所以你有能力跟踪活动,如果被滥用,可能会减少请求的数量。

最安全的方法是使用SSL通道并请求身份验证。如果身份验证通过,那么您可以向客户端返回某种会话密钥(可以是随机生成的字符串),并在每次请求时对其进行检查。

如果你的服务不允许使用SSL,那么你可以尝试为你的合作伙伴添加简单的用户名/密码身份验证,但在这种情况下,如果有人拦截了你的通信,他们可以使用相同的凭据访问你的服务。

另一种方法是对每个请求使用签名。例如,您可以将GPG用于此目的。您的服务器持有您所有合作伙伴的公钥。当合作伙伴想向您的服务器进行查询时,他只需用私钥签署他的请求,在收到请求后,您将能够安全地验证该请求是由特定合作伙伴发送的,并且100%不是伪造的。

编辑

对于GPG,您需要安装名为gnupg的PECL模块。这是我们框架中使用GPG功能的类。

class GPG
{
    /**
     * Encrypt given data to one or more recipients
     * 
     * @param string $string
     * @param string|array $encryptKeyID
     * @param bollean $armour
     * @return string
     */
    public static function encrypt($string, $encryptKeyID, $armour = true){
        $gpg = new Crypt_GPG();
        if(is_array($encryptKeyID)){
            foreach($encryptKeyID as $keyId){
                $gpg->addEncryptKey($keyId);
            }
        }
        else{
            $gpg->addEncryptKey($encryptKeyID);
        }
        return $gpg->encrypt($string, $armour);
    }
    /**
     * Decrypt given data
     *  
     * @param string $string
     * @param string $keyPassword
     * @param string $keyID
     * @return string
     */
    public static function decrypt($string, $keyID, $keyPassword = null){
        $gpg = new Crypt_GPG();
        $gpg->addDecryptKey($keyID, $keyPassword);
        return $gpg->decrypt($string);
    }
    /**
     * Sign given string
     * 
     * @param string $string
     * @param string $keyID
     * @param string $keyPassword
     * @param boolean $mode
     * @param boolean $armor
     * @return string
     */
    public static function sign($string, $keyID, $keyPassword = null, $mode = null, $armor = true){
        $gpg = new Crypt_GPG();
        if($mode === null){
            $mode = Crypt_GPG::SIGN_MODE_CLEAR;
        }
        $gpg->addSignKey($keyID, $keyPassword);
        return $gpg->sign($string, $mode);
    }
    /**
     * Verify signature of given message
     * 
     * @param string $string
     * @return boolean
     */
    public static function verify($string){
        $gpg = new Crypt_GPG();
        $signatures = $gpg->verify($string);
        if ($signatures[0]->isValid()) {
            return true;
        } 
        else{
            return false;
        }
    }
    /**
     * Encrypt and sign given string to one or more recipients
     * 
     * @param string $string
     * @param string|array $encryptKeyID
     * @param string $signkeyID
     * @param string $signkeyPassword
     * @param boolean $mode
     * @param boolean $armor
     * @return string
     */
    public static function encryptAndSign($string, $encryptKeyID, $signkeyID, $signkeyPassword = null, $mode = null, $armor = true){
        $gpg = new Crypt_GPG();
        if($mode === null){
            $mode = Crypt_GPG::SIGN_MODE_CLEAR;
        }
        $gpg->addSignKey($signkeyID, $signkeyPassword);
        if(is_array($encryptKeyID)){
            foreach($encryptKeyID as $keyId){
                $gpg->addEncryptKey($keyId);
            }
        }
        else{
            $gpg->addEncryptKey($encryptKeyID);
        }
        return $gpg->encryptAndSign($string, $armor);
    }
    /**
     * Decrypt and verify given string
     * 
     * @param string $string
     * @param string $keyID
     * @param string $keyPassword
     * @return array|false
     */
    public static function decryptAndVerify($string, $keyID, $keyPassword = null){
        $gpg = new Crypt_GPG();
        $gpg->addDecryptKey($keyID, $keyPassword);
        $result = $gpg->decryptAndVerify($string);
        if(empty($result['data']) and empty($result['signatures'])){
            return false;
        }
        if(isset($result['signatures'][0])){
            $result['signature'] = $result['signatures'][0]->isValid();
            unset($result['signatures']);
        }
        return $result;
    }
}