3

Web サービス (RESTful ではない) に POST しようとしていて、PHP から応答を得ようとしています。ただし、その Web サービスにはダイジェスト認証が必要です。

私はオンラインで検索してきましたが、ほとんどの議論や記事は、PHP を使用して応答するのではなく、その逆 (ユーザーへのダイジェスト認証の要求) に関するものであることがわかりました。

このスレッドが提供するコードを使用してダイジェスト応答を生成できます: HTTP Digest authenticationing in PHPですが、問題はそれを POST データと一緒に (またはそうではなく) 送信することです。

私が使用しているコードは次のとおりです。

$domain = "https://api.example.com";
$uri = "/ws.asmx/do";

// get headers
$response1_array = get_headers($web_service_url);
// get request part of digest auth
$response1 = $response1_array[5];
// get things behind "WWW-Authenticate:"
$response1 = substr($response1, 18);

// response() is a invented function to calculate the response according to the RFC2617
$response2 = response($response1, "username", "password", "GET", $uri);

// manually add some headers for POST, and fill out the parts that the calculation function missed
// for auth
$header =  
        "Host: api.example.com\r\n" .
        "Content-Type: application/x-www-form-urlencoded\r\n" .
        "Authorization: " . $response2 . ", nc=\"00000001\", opaque=\"0000000000000000\"" . "\r\nContent-Length: 0\r\n\r\n";

// echo the response from server
echo do_post_request($web_service_url, "", $header);

function do_post_request($url, $data, $optional_headers = null)
{
  $params = array('http' => array(
              'method' => 'POST',
              'content' => $data
            ));
  if ($optional_headers !== null) {
    $params['http']['header'] = $optional_headers;
  }
  $ctx = stream_context_create($params);

  $fp = fopen($url, 'rb', false, $ctx);

  if (!$fp) {
    throw new Exception("Problem with $url");
  }
  $response = stream_get_contents($fp);
  if ($response === false) {
    throw new Exception("Problem reading data from $url");
  }
  return $response;
}

応答では:

$response1(from web service):
    Digest realm="example.com", nonce="OS82LzIwMTMgMTI6MDI6NDYgUE0", opaque="0000000000000000", stale=false, algorithm=MD5, qop="auth"

$response2(I calculated given the server response):
    Digest username="username", realm="example.com", nonce="OS82LzIwMTMgMTI6MDI6NDYgUE0", uri="/ws.asmx/do", cnonce="1378494106", nc="1", response="0f96788854cf2098ba22c6121529d7de", qop="auth"

the final (2nd) response from server:
    Warning: fopen(https://api.example.com/ws.asmx/do): failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error in ...

この場合、サーバーが 500 エラーを返した理由がわかりません。コードに何か問題がありますか? または、以前にこの問題に遭遇して解決し、解決策を手伝ってくれる人はいますか?

よろしく、

マイロ

4

2 に答える 2

25

2日間手探りした後、最終的にcURLで解決しました。ダイジェスト認証用の既製の PHP コードが投稿されたのはこれが初めてだと思います。うまくいけば、私と同じ溝にいる誰かを助けることができます.

コード:

<?php

error_reporting(E_ALL); 
ini_set( 'display_errors','1');

$url = "https://api.example.com/ws.asmx/do";
$username = "username";
$password = "pwd";
$post_data = array(
        'fieldname1' => 'value1',
        'fieldname2' => 'value2'
  );

$options = array(
        CURLOPT_URL            => $url,
        CURLOPT_HEADER         => true,    
        CURLOPT_VERBOSE        => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_SSL_VERIFYPEER => false,    // for https
        CURLOPT_USERPWD        => $username . ":" . $password,
        CURLOPT_HTTPAUTH       => CURLAUTH_DIGEST,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => http_build_query($post_data) 
);

$ch = curl_init();

curl_setopt_array( $ch, $options );

try {
  $raw_response  = curl_exec( $ch );

  // validate CURL status
  if(curl_errno($ch))
      throw new Exception(curl_error($ch), 500);

  // validate HTTP status code (user/password credential issues)
  $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  if ($status_code != 200)
      throw new Exception("Response with Status Code [" . $status_code . "].", 500);

} catch(Exception $ex) {
    if ($ch != null) curl_close($ch);
    throw new Exception($ex);
}

if ($ch != null) curl_close($ch);

echo "raw response: " . $raw_response; 

?>
于 2013-11-09T01:22:10.130 に答える