0

像我五岁一样向我解释,大声笑。作为一名 web 开发人员,我只使用传统的 websetup:我有一个 Java 应用程序,我将它部署到某处的服务器,然后使用 web 浏览器连接/测试它。如果需要来回发送敏感信息,例如密码,则使用 SSH 服务器。

现在我已经在 J​​ava Play 中编写了一个 RESTful 应用程序!我想部署到 Amazon EC2 实例上。我一直无法理解 PCI 安全性的概念以及如何将其应用到我的设置中。在这种情况下,我希望 REST 应用程序允许管理功能,因此需要将登录凭据添加到提交给各种 REST 服务的请求中。

在亚马逊 EC2 端和客户端(基于 Jersey 的客户端)上执行此操作的最佳方法是什么。

4

2 回答 2

1

一般来说,在 URL 中只需要用户名密码是个坏主意。即使您使用 SSL,URL 及其所有查询参数也不安全。如果您希望您的提要是安全的,您可以使用诸如 HMAC-SHA1 或 HMAC-SHA256 之类的散列方法使用私钥对您的请求进行签名。它的工作原理是这样的。

客户端需要两个密钥,公钥和私钥

PublicKey: ABCDJJJZ7BW9P0IH2NI3
PrivateKey: uFehWXvcM7mf==c8ZhOe3Fz+6d+zyQ2ja4A3De1N

从动词、url、标题和正文构建一个字符串。建议您使用 SSL 或在 url 中包含 Expire 参数,以防止任何黑客有效地执行重放攻击。确保日期和主机包含在标题中,日期对于确保签名始终在变化非常重要。

verb + \n
url + \n
header1: value + \n
header2: value + \n
body

然后客户端使用上述哈希方法对请求进行签名。伪代码看起来像这样。

base64encode(hmac-sha1($private_key, $string_to_sign))

a 标头附加到包含签名和公钥的请求中

Authorization: $public_key:$signature

当服务器收到消息时,他们使用标头中收到的公钥为用户检索私钥Authorization。然后服务器执行相同的算法,如果两个签名匹配,则服务器知道请求已通过身份验证,因为只有具有正确公钥和私钥的客户端才能生成相同的签名。

这是使用此算法签署请求的 PHP 代码片段。

public function sign() {
    $time = time();
    $date = gmdate(self::DATE_FORMAT_RFC2616, $time);
    $verb = $this->payload['verb'];
    $headers = $this->payload['headers'];
    $query = $this->payload['query'];
    $body = $this->payload['body'];

    // Build the content string
    $endpoint = $this->endpoint;        

    // Set the expiration time of the request
    if($this->expires != 0 && !isset($query['Expires'])) {
        $query['Expires'] = $time + ($this->expires * 60);
    }

    // Add the date to the request headers
    $headers['date'] = $date;

    // Add the host to the request headers 
    $headers['host'] = $this->host;

    // Sort the query array and convert to querystring
    uksort($query, 'strnatcasecmp');
    $querystring = SUUtilities::to_query_string($query); 

    // Sort the headers to be sure they're in the right order
    $modified_headers = array();
    uksort($headers, 'strnatcasecmp');

    // Concatinate the headers so the key and value are a single string
    $include = array('date', 'host');
    foreach($headers as $key => $value) {
        if(in_array($key, $include) || substr($key, 0, 5) == "x-sbr") {
            $modified_headers[] = preg_replace('/\s/', '', strtolower($key)).": ".$value;
        }
    }

    // Build the string to sign
    $string_to_sign = $verb.PHP_EOL
        .$endpoint."?".$querystring.PHP_EOL
        .implode(PHP_EOL, $modified_headers).PHP_EOL
        .$body;

    // Create the signature for the request
    $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->credentials['private_key'], true));

    // Add the authorization header to the list of headers.
    array_push($modified_headers, 'authorization: SBR '.$this->credentials['key'].':'.$signature);

    $request = array();
    $request['headers'] = $modified_headers;
    $request['host'] = $this->host;
    $request['endpoint'] = $endpoint;
    $request['query'] = $query;     

    return $request;
}

其他资源:

于 2013-02-05T15:13:46.713 回答
0

如果您的客户端丢弃了 cookie,您可以让 REST 服务检查 cookie,如果 cookie 不存在则返回 Forbidden。另一种方法是需要一个参数,该参数采用 URL 的动态片段(随着大多数请求而变化)并使用 REST 服务已知的私钥对其进行 SHA 编码。

于 2013-02-05T04:18:36.830 回答