使用PHP POST到Web服务的摘要身份验证的客户端部分 [英] Client part of the Digest Authentication using PHP POST to Web Service

查看:290
本文介绍了使用PHP POST到Web服务的摘要身份验证的客户端部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试发布到Web服务(不是RESTful)并通过PHP获得响应.但是,该Web服务需要摘要式身份验证.

I'm trying to POST to a Web Service (not RESTful) and get response through PHP. However, that web service requires Digest Authentication.

我一直在网上搜索,发现大多数讨论和文章都是关于另一种方式(向用户请求摘要身份验证),而不是使用PHP进行响应.

I've been searching online and found most of the discussions and articles are about the other way around (Requesting Digest Authentications to users), instead of responding it, using PHP.

我能够使用该线程提供的代码生成摘要响应: HTTP摘要认证在PHP 中,但是问题是将它与POST数据一起发送(或不发送).

I'm able to generate the Digest response using the code this thread provide:HTTP Digest authenticating in PHP, but the problem is to sending it along with(or not?) the POST data.

这是我正在使用的代码:

Here's the code I'm using:

$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错误.代码有什么问题吗?还是以前有人遇到过这个问题并解决了该问题,可以为我提供解决方案?

I don't understand why server responded 500 error in this case. Is there anything wrong in the code? Or has anyone met this problem before and solved it and can help me with a solution?

此致

Mylo

推荐答案

经过2天的摸索,最终使用cURL对其进行了解决.我想这是第一次发布用于摘要认证的现成的PHP代码,希望它可以帮助与我同处的人.

Eventually solved it with cURL after 2 days' fumbling. I guess this is the first time a piece of ready-made PHP code for digest auth is posted, hopefully it can help someone who are in the same ditch as I was in.

代码:

<?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; 

?>

这篇关于使用PHP POST到Web服务的摘要身份验证的客户端部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆