问题
I am using some Magento 2.3 REST calls, and I am finding that for certain calls (and it seems to be consistently GETs) Magento is returning an authentication error, while for others (which seem to be consistently POST/PUTs) the call is succeeding. I am getting an Admin token (without any problem - this is a POST) and using Bearer authentication, then using the same token on calls that succeed and ones that don't. My user is defined to Magento as an Administrator, with access to All.
I am working in a test environment which is subject to change. I have been working for some months without this problem. Then basic authentication was switched on on the server, which got in the way of everything, as you cannot put both Basic and Bearer authentication details into a single call. However my IP was then whitelisted, and I can now browse to the server without hitting the basic authentication screen, and as I say some of the REST calls work, but not all.
I have a test PHP program set up that:
- Sets values such as host address, user, password etc
- Gets the admin token;
- Use GET /rest/V1/orders/{id} to get details of an order
- Uses POST /rest/V1/orders to set the status of the same order
For the GET and POST calls I have the Verbose option switched on.
The token code is:
// Get handle for token retrieval
$userData = array("username" => $user, "password" => $pwd);
$ch = curl_init("https://" . $host . "/rest/V1/integration/admin/token/");
// Set options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($userData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json",
"Content-Length: " . strlen(json_encode($userData))));
// Get token
echo "<PRE>*** Getting Magento Token *** </PRE>";
$token = curl_exec($ch);
$magento_token = json_decode($token);
echo "Value returned: " . $token . "<BR><BR><BR><BR>";
The GET code is:
// Execute REST request to get order details
$ch = curl_init("https://" . $host . "/rest/V1/orders/" . $increment_id);
// Set options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json",
"Authorization: Bearer " . $magento_token));
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('/tmp/curl.log', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// Get details
echo "<PRE>*** Getting Order Details *** </PRE>";
$result = curl_exec($ch);
echo "Value returned: " . $result . "<BR><BR>";
// Display log
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
echo "<BR>Verbose information 1:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
The POST code is:
// Set up parameter array
$post_params = Array("entity" =>
Array("entity_id" => $entity_id,
"increment_id" => "$increment_id",
"state" => "processing",
"status" => "picked"));
$params = "fields=increment_id,state,status";
// Execute REST request to get order details
$ch = curl_init("https://" . $host . "/rest/V1/orders/?" . $params);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json",
"Authorization: Bearer " . $magento_token,
"Content-Length: " . strlen(json_encode($post_params))));
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('/tmp/curl.log', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// Get details
echo "<BR><BR><BR><PRE>*** Setting Order Status *** </PRE>";
$result = curl_exec($ch);
echo "Value returned: " . $result . "<BR><BR>";
// Display log
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
echo "<BR>Verbose information 2:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
The display when I run the program is given below. As can be seen, the token is returned without problem, and both the GET and the POST use it, but the GET fails.
Output:
*** Getting Magento Token ***
Value returned: "ghai1n05532d9rztojfv2cuxfrw7gcw5"
*** Getting Order Details ***
Value returned: {"message":"The consumer isn't authorized to access
%resources.","parameters":{"resources":"Magento_Sales::actions_view"},"trace":"#0
\/var\/www\/sand2\/public_html\/vendor\/magento\/module-webapi\/Controller\/Rest\/RequestValidator.php(68):
Magento\\Webapi\\Controller\\Rest\\RequestValidator->checkPermissions()\n#1
\/var\/www\/sand2\/public_html\/vendor\/magento\/module-webapi\/Controller\/Rest\/InputParamsResolver.php(80):
Magento\\Webapi\\Controller\\Rest\\RequestValidator->validate()\n#2
\/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/Interception\/Interceptor.php(58):
Magento\\Webapi\\Controller\\Rest\\InputParamsResolver->resolve()\n#3
\/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/Interception\/Interceptor.php(138):
Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callParent('resolve', Array)\n#4
\/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/Interception\/Interceptor.php(153):
Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->Magento\\Framework\\Interception\\{closure}()\n#5
\/var\/www\/sand2\/public_html\/generated\/code\/Magento\/Webapi\/Controller\/Rest\/InputParamsResolver\/Interceptor.php(26):
Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callPlugins('resolve', Array, Array)\n#6
\/var\/www\/sand2\/public_html\/vendor\/magento\/module-webapi\/Controller\/Rest\/SynchronousRequestProcessor.php(85):
Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->resolve()\n#7
\/var\/www\/sand2\/public_html\/vendor\/magento\/module-webapi\/Controller\/Rest.php(188):
Magento\\Webapi\\Controller\\Rest\\SynchronousRequestProcessor->process(Object(Magento\\Framework\\Webapi\\Rest\\Request\\
Proxy))\n#8 \/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/Interception\/Interceptor.php(58):
Magento\\Webapi\\Controller\\Rest->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#9
\/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/Interception\/Interceptor.php(138):
Magento\\Webapi\\Controller\\Rest\\Interceptor->___callParent('dispatch', Array)\n#10
\/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/Interception\/Interceptor.php(153):
Magento\\Webapi\\Controller\\Rest\\Interceptor->Magento\\Framework\\Interception\\{closure}(Object(Magento\\Framework\\App\\
Request\\Http))\n#11
\/var\/www\/sand2\/public_html\/generated\/code\/Magento\/Webapi\/Controller\/Rest\/Interceptor.php(26):
Magento\\Webapi\\Controller\\Rest\\Interceptor->___callPlugins('dispatch', Array, Array)\n#12
\/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/App\/Http.php(137):
Magento\\Webapi\\Controller\\Rest\\Interceptor->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#13
\/var\/www\/sand2\/public_html\/vendor\/magento\/framework\/App\/Bootstrap.php(261):
Magento\\Framework\\App\\Http->launch()\n#14 \/var\/www\/sand2\/public_html\/pub\/index.php(40):
Magento\\Framework\\App\\Bootstrap->run(Object(Magento\\Framework\\App\\Http\\Interceptor))\n#15 {main}"}
Verbose information 1:
* About to connect() to [my_host] port 443 (#5)
* Trying [host_ip]...
* Connected to [my_host] ([host_ip]) port 443 (#5)
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=ssl379212.cloudflaressl.com,OU=PositiveSSL Multi-Domain,OU=Domain Control Validated
* start date: Jun 07 00:00:00 2019 GMT
* expire date: Dec 14 23:59:59 2019 GMT
* common name: ssl379212.cloudflaressl.com
* issuer: CN=COMODO ECC Domain Validation Secure Server CA 2,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
> GET /rest/V1/orders/1000099861 HTTP/1.1
Host: [my_host]
Accept: */*
Content-Type: application/json
Authorization: Bearer ghai1n05532d9rztojfv2cuxfrw7gcw5
< HTTP/1.1 401 Unauthorized
< Date: Sun, 14 Jul 2019 12:14:40 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 3034
< Connection: keep-alive
< Set-Cookie: __cfduid=d7f7294db28f5aa2210b0d4349cc484fc1563106480; expires=Mon, 13-Jul-20 12:14:40 GMT; path=/; domain=[my_domain]; HttpOnly
< X-UA-Compatible: IE=edge
< Pragma: no-cache
< Expires: -1
< Cache-Control: no-store, no-cache, must-revalidate, max-age=0
< Set-Cookie: PHPSESSID=8fuvj627r81k74iv5gs1oofv8s; expires=Sun, 14-Jul-2019 13:14:40 GMT; Max-Age=3600; path=/; domain=[my_host]; secure; HttpOnly
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 4f636aed1bcc35a0-LHR
<
* Connection #5 to host [my_host] left intact
*** Setting Order Status ***
Value returned: {"increment_id":"1000099861","state":"processing","status":"picked"}
Verbose information 2:
* About to connect() to [my_host] port 443 (#6)
* Trying [host_ip]...
* Connected to [my_host] ([host_ip]) port 443 (#6)
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=ssl379212.cloudflaressl.com,OU=PositiveSSL Multi-Domain,OU=Domain Control Validated
* start date: Jun 07 00:00:00 2019 GMT
* expire date: Dec 14 23:59:59 2019 GMT
* common name: ssl379212.cloudflaressl.com
* issuer: CN=COMODO ECC Domain Validation Secure Server CA 2,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
> POST /rest/V1/orders/ HTTP/1.1
Host: [my_host]
Accept: */*
Content-Type: application/json
Authorization: Bearer ghai1n05532d9rztojfv2cuxfrw7gcw5
Content-Length: 90
* upload completely sent off: 90 out of 90 bytes
< HTTP/1.1 200 OK
< Date: Sun, 14 Jul 2019 12:14:40 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 2164
< Connection: keep-alive
< Set-Cookie: __cfduid=d9b640ef9a03429671731b1d18271062b1563106480; expires=Mon, 13-Jul-20 12:14:40 GMT; path=/; domain=[my_domain]; HttpOnly
< X-Frame-Options: SAMEORIGIN
< X-UA-Compatible: IE=edge
< Pragma: no-cache
< Expires: -1
< Cache-Control: no-store, no-cache, must-revalidate, max-age=0
< Accept-Ranges: bytes
< Set-Cookie: PHPSESSID=1hvd98s6lmd0ajqjlk6qpmk6lq; expires=Sun, 14-Jul-2019 13:14:40 GMT; Max-Age=3600; path=/; domain=[my_host]; secure; HttpOnly
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 4f636aee1d4adc4b-LHR
<
* Connection #6 to host [my_host] left intact
* Added Note * To make the problem a bit weirder, I've found that I can get the information I want (in this example at any rate) in a slightly roundabout way. Like many of the POST/PUT calls in the Magento 2 REST API, the POST above actually returns all the data for the order in question (or a subset if I add a 'fields' query parameter). So I can use the POST to set some known attribute of the order to the value that I know it has already, then read off the data I want from the returned JSON string in exactly the same way as I would read it off from the GET call if that succeeded. For some reason Magento is quite happy for me to access the data through the POST, but not through the GET. Does that make any sense???
回答1:
Changing the PHP handler from cgi to suphp solved the problem. The GET requests now work along with the POST requests. I have no idea how the handler can be responsible for this obscure problem, so if anyone can shed any light, I would be grateful.
来源:https://stackoverflow.com/questions/57028498/problem-with-magento-2-rest-authentication