1

*我试图找出如何实现“最简单”的身份识别形式,以便我的合作伙伴网站访问我的网络服务以检索信息。*

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

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

我看不出将唯一标识符作为 URL 中的参数传递有何帮助,因为“任何人”都可以捕获该数据并自己使用它。但我会将其用作附加检查。

所以我想出的唯一“安全”方法是识别访问我网站的网站,然后根据我服务器上的列表进行控制。

我将不胜感激有关哪些方法“最安全”的反馈。

4

2 回答 2

2

最安全的方法是使用 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;
    }
} 
于 2012-04-04T09:51:52.510 回答
2

Web 服务中的常见做法是使用公钥/私钥来验证 API 请求。一些使用它们的示例网站:Google、Twitter、EventBriteLast.FM、GitHub 等。

这些通过拥有每个人都知道的公共或消费者密钥来工作。然后为每个用户提供一个私钥或密钥以允许身份验证。使用这个很酷的事情是,因为您确切地知道谁在发出请求,所以您有能力跟踪活动并在被滥用时可能会限制请求的数量。

于 2012-04-04T10:35:46.740 回答