【问题标题】:cURL Equivalent to xhrFields: {withCredentials: true}cURL 等效于 xhrFields: {withCredentials: true}
【发布时间】:2018-05-20 22:15:11
【问题描述】:

目标:

使用他们的 API 登录到处理器的站点,并将成功响应存储到我站点上的 COOKIE 和 SESSION 中。

几乎可行的方法:

jQuery(document).ready(function($){
    $.ajax({
      type: 'POST',
      url: '{url-to-api-call}',
      xhrFields: {
        withCredentials: true
      },
      dataType: 'text',
      data: 'Email={email}&GuestSessionToken={token}&Password={pass}&Format=JSON&RememberMe=true',
      processData: false,
      crossDomain: true,
      success: function (res) { console.log('success'); },
      error: function (jqXHR, textStatus, ex) {
          console.log('error');
      }
    });
});

为什么它不起作用: 我无法存储对 COOKIE 和 SESSION 的响应。


我想从事什么工作:

$url = {url-to-api};
$curl = curl_init();
$curl_post_data = array(
    'Email' => $fields['user_email'],
    'GuestSessionToken' => $_COOKIE['SessionToken'],
    'Password' => $fields['user_pass'],
    'Format' => "JSON",
    'RememberMe' => "true"
);
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,5);
curl_setopt($curl, CURLOPT_TIMEOUT, 90);

$content = curl_exec($curl);
curl_close($curl);
$content_array = json_decode($content, true);

if ($content_array['StatusCode'] == 'OK') {
    $fields['UserId'] = $content_array['Data']['UserId'];
    $fields['SessionID'] = $content_array['Data']['ID'];
    $fields['SessionToken'] = $content_array['Data']['Token'];
    return true;
} else {
    $errors->add( 'error', 'Unable to sign in.' );
    return false;
}

为什么它不起作用: 这将返回一个成功响应,我可以使用它来设置 COOKIE 和 SESSION,但它不会让用户登录到处理器的站点。

为什么我认为它不起作用: 在我添加 xhrFields 部分之前,ajax 调用不会让用户登录。我想如果我能找到一个与 xhrFields 部分等效的 cURL,我就准备好了。

提前致谢!

我的胶带修复。

<?php

// If signin form is submitted and signin cURL was successful.
echo (isset($fields['signin_script'])) ? $fields['signin_script'] : "";

function processor_signin(&$fields, &$errors) {

    $url = '{url-to-api-call}';
    $curl = curl_init();
    $curl_post_data = array(
        'Email' => $fields['user_email'],
        'GuestSessionToken' => $_COOKIE['SessionToken'],
        'Password' => $fields['user_pass'],
        'Format' => "JSON",
        'RememberMe' => "true"
    );
    curl_setopt($curl,CURLOPT_URL,$url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
    curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,5);
    curl_setopt($curl, CURLOPT_TIMEOUT, 90);

    $content = curl_exec($curl);
    curl_close($curl);
    $content_array = json_decode($content, true);

    if ($content_array['StatusCode'] == 'OK') {
        $fields['UserId'] = $content_array['Data']['UserId'];
        $fields['SessionID'] = $content_array['Data']['ID'];
        $fields['SessionID'] = $content_array['Data']['ID'];
        $fields['SessionToken'] = $content_array['Data']['Token'];

        // Duct tape fix
        $fields['signin_script'] = "
        <script>
            jQuery(document).ready(function($){
                $.ajax({
                  type: 'POST',
                  url: '{url-to-api-call}',
                  xhrFields: {
                    withCredentials: true
                  },
                  dataType: 'text',
                  data: '
                    Email=".$fields['user_email']."
                    &GuestSessionToken=".$_COOKIE['SessionToken']."
                    &Password=".$fields['user_pass']."
                    &Format=JSON
                    &RememberMe=true',
                  processData: false,
                  crossDomain: true,
                  success: function (res) { console.log('signin success'); },
                  error: function (jqXHR, textStatus, ex) {
                      console.log('signin error');
                  }
                });
            });
        </script>
        ";

        return true;
    } else {
        $errors->add( 'error', 'Unable to sign in.' );
        return false;
    }

}
?>

【问题讨论】:

  • withCredentials 是关于 CORS,告诉浏览器包含来自其他站点的 cookie。这在不存储 cookie 的 curl 中没有任何意义。您需要自己发送 cookie。
  • 我希望您不要幻想您可以从您的服务器端代码在浏览器中为其他域设置 cookie ...?
  • @CBroe 使用上面的 AJAX 请求(由处理器提供)将用户登录到处理器站点并在成功时返回以下响应。 {"OK":true,"Data":{"ID":ID-HERE,"UserId":USER-ID,"Token":"TOKEN"},"StatusCode":"OK"} 如果我能弄清楚然后使用该响应在本地将 ID 和 TOKEN 设置为 COOKIE 和 SESSION 的一种方法,这是可行的。

标签: php ajax session curl cookies


【解决方案1】:

也许您已登录但未存储 cookie。

因此,您需要解析标头并最终存储所有 cookie。在处理请求时,您需要发回您之前检索到的所有 cookie。

这是一个如何从服务器检索 cookie 和其他标头的示例:

public function sendRequest(HttpRequest $request) 
{
    ...
    curl_setopt($ch, CURLOPT_HTTPHEADER, $request->getHeaders());
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, [$this, 'fetchHeader']);
    ...
    $content = curl_exec($ch);
    ...
}

/**
 * @param resource $ch     - curl handle
 * @param string   $header
 *
 * @return int
 */
private function fetchHeader($ch, $header)
{
    $headerParts = explode(': ', $header, 2);
    if (2 === count($headerParts)) {
        $headerName = strtolower($headerParts[0]);
        if ('set-cookie' === $headerName) {
            $this->responseHeaders[$headerName][] = trim($headerParts[1]);
            return strlen($header);
        }
        $this->responseHeaders[$headerName] = trim($headerParts[1]);
    }
    return strlen($header);
}

【讨论】:

  • 我一直在努力解决这个问题,但目前它只是超出了我的范围。我很感激你的回答,并希望我能用它做更多的事情。我想我需要更多地了解 cURL 和 headers 的工作原理。
  • 当您从服务器接收 cookie 时,它​​们位于名为“set-cookie”的响应标头中。也许这个链接有帮助:developer.mozilla.org/de/docs/Web/HTTP/Cookies 确保在收到 cookie 后存储它们,然后在“cookie”请求标头中发送回服务器。
猜你喜欢
  • 1970-01-01
  • 2012-07-01
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-15
相关资源
最近更新 更多