经过数小时的思考这个问题,我终于意识到为什么我们中的一些人会收到以下错误:
Invalid auth/bad request (got a 403, expected HTTP/1.1 20X or a redirect)
{"messages":{"error":[{"code":403,"message":"Access denied"}]}}
即使在成功授权管理员/客户之后。
不幸的是,问题不在于 Magento,而很可能是您的服务器配置。
我开始研究 Magento Api2 代码并意识到他们正在使用 Zend_Controller_Request_Http 方法“getHeader”来检查 oAuth 授权。
以下是“getHeader()”的代码
public function getHeader($header)
{
if (empty($header)) {
#require_once 'Zend/Controller/Request/Exception.php';
throw new Zend_Controller_Request_Exception('An HTTP header name is required');
}
// Try to get it from the $_SERVER array first
$temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
if (isset($_SERVER[$temp])) {
return $_SERVER[$temp];
}
// This seems to be the only way to get the Authorization header on
// Apache
if (function_exists('apache_request_headers')) {
$headers = apache_request_headers();
if (isset($headers[$header])) {
return $headers[$header];
}
$header = strtolower($header);
foreach ($headers as $key => $value) {
if (strtolower($key) == $header) {
return $value;
}
}
}
return false;
}
Magento 类“Mage_Api2_Model_Auth_Adapter_Oauth”传递给这个函数的是:
public function isApplicableToRequest(Mage_Api2_Model_Request $request)
{
$headerValue = $request->getHeader('Authorization');
return $headerValue && 'oauth' === strtolower(substr($headerValue, 0, 5));
}
由于正在调用 "$request->getHeader('Authorization'),这意味着 getHeader 函数中的 $header var 是 "Authorization"
// Try to get it from the $_SERVER array first
$temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
if (isset($_SERVER[$temp])) {
return $_SERVER[$temp];
}
Zend 类然后将“授权”转换为“HTTP_AUTHORIZATION”并在 $_SERVER 数组中查找它,这就是问题所在,因为在该数组中授权值位于“$_SERVER['Authorization']”而不是“$ _SERVER['HTTP_AUTHORIZATION"]",他们这样做是因为其他变量(例如 CONTENT_TYPE)存储为 HTTP_CONTENT_TYPE,授权除外。
然而,Zend 似乎意识到了这一点,因此他们编写了以下代码:
// This seems to be the only way to get the Authorization header on
// Apache
if (function_exists('apache_request_headers')) {
$headers = apache_request_headers();
if (isset($headers[$header])) {
return $headers[$header];
}
$header = strtolower($header);
foreach ($headers as $key => $value) {
if (strtolower($key) == $header) {
return $value;
}
}
}
这里的问题是那里的许多服务器没有启用“apache_request_headers”,如果您遇到这个问题,很可能您的托管公司禁用了“apache_request_headers”。
这里有2个解决方案:
- 联系您的主机并要求他们启用“apache_request_headers”。
- 修改 Zend_Controller_Request_Http 类中的 getHeader($header) 函数
代替:
$temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
和:
$temp = ($header == 'Authorization') ? $header : 'HTTP_' . strtoupper(str_replace('-', '_', $header));