Joined: 07 Mar 2014 |
Posts: 1 |
Location: Brasil |
|
|
Posted: Fri Mar 07, 2014 11:04 am |
|
|
|
|
|
I'm trying for a long time to implement a webservice with digest authentication using nusoap.
I allways get the same error: HTTP Error: Too many tries to get an OK response (HTTP/1.0 401 Unauthorized)
I just want some simple example that works with digest authentication.
Can anyone help me?
I'm trying the following:
Script client.php
<?php
require_once ('lib/nusoap.php');
require_once ('authenticate.php');
$service = 'http://localhost/testes/ws/server.php';
$wsdl = $service.'?wsdl';
$secure = $service.'?secure';
$digest = getDigestToServer($secure); //implemented at authenticate.php script, below
$client = new soapclient($wsdl, true);
$client->setCredentials($validUser,$validPass,"digest",
array(
"realm" => $digest["realm"],
"nonce" => $digest["nonce"],
"nc" => 0,
"qop" => $digest["qop"],
"opaque" => $digest["opaque"],
));
echo "<br>";
echo "Getting professional code for '123.456.789-10','TÉCNICO'.<br>";
$result = $client->call('getRegistro', array('123.456.789-10','TÉCNICO'));
if($result == false){
echo "Fail: <pre>".$client->getError()."</pre>";
}
else{
$erro = $client->getError();
if($erro){
echo "Error: <pre>$erro</pre>";
}else{
echo "SUCESS!<br>";
echo "Answer (json): $result<br>";
var_dump(json_decode($result));
}
}
echo "<textarea id='txt1' name='txt1'>
Request:\n".$client->request."\n\n
Reply:\n".$client->response."\n\n
</textarea>
<br>
Debug:<br><fieldset>".$client->debug_str."</fieldset>";
?>
|
Script server.php
<?php
if(isSet($_REQUEST["secure"])){
include("authenticate.php");
requireAuthentication(); //implemented at authenticate.php script, below
}
//Enable webservice
require_once ('lib/nusoap.php');
//using soap_server to create server object
$server = new soap_server;
//Configurando o serviço de consulta de registros
$server->configureWSDL('server.getRegistro', 'urn:server.getRegistro');
$server->wsdl->schemaTargetNamespace = 'urn:server.getRegistro';
//register a function that works on server
$server->register( 'getRegistro', //Nome da função
array( 'cpf' => 'xsd:string', //Parametros da função
'categoria' => 'xsd:string'),
array('return' => 'xsd:string'), //Valor de retorno
'urn:server.getRegistro', //Namespace
'urn:server.getRegistro#getRegistro', //SOAP Action
'rpc', //Style
'encoded', //Use
'Consulta o número de registro de um profissional de enfermagem.' //Descricao do serviço
);
// create HTTP listener
$HTTP_RAW_POST_DATA = (isSet($HTTP_RAW_POST_DATA)) ? $HTTP_RAW_POST_DATA:'';
$server->service($HTTP_RAW_POST_DATA);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Function
function getRegistro($cpf, $categoria){
include("authenticate.php"); //implemented below
//This example works fine if you comment the line below. I'm not sure where to place this line
requireAuthentication(); //implemented at authenticate.php script, below
$rc = array();
$rc["cpf"] = preg_replace("([^0-9])", "", $cpf); //removing '.' and '-'
$rc["categoria"] = utf8_encode($categoria);
$rc["registro"] = date("dmYhis"); //returning professional code
return json_encode($rc);
}
?>
|
Script authenticate.php
<?php
$realm = 'my_realm_code';
$validUser = 'admin';
$validPass = '1234';
function requireAuthentication() //Used by server.php script, above
{
global $realm, $validUser, $validPass;
// Just a random id
$nonce = uniqid();
// Get the digest from the http header
$digest = getDigest();
// If there was no digest, show login
if (is_null($digest)) requireLogin($realm,$nonce);
$digestParts = digestParse($digest);
// Based on all the info we gathered we can figure out what the response should be
$A1 = md5("{$validUser}:{$realm}:{$validPass}");
$A2 = md5("{$_SERVER['REQUEST_METHOD']}:{$digestParts['uri']}");
$validResponse = md5("{$A1}:{$digestParts['nonce']}:{$digestParts['nc']}:{$digestParts['cnonce']}:{$digestParts['qop']}:{$A2}");
if ($digestParts['response']!=$validResponse) requireLogin($realm,$nonce);
// We're in!
//echo 'Well done sir, you made it all the way through the login!';
}
// This function returns the digest string
function getDigest() {
$digest = '';
// mod_php
if (isset($_SERVER['PHP_AUTH_DIGEST'])) {
$digest = $_SERVER['PHP_AUTH_DIGEST'];
// most other servers
}
elseif (isset($_SERVER['HTTP_AUTHENTICATION'])) {
if (strpos(strtolower($_SERVER['HTTP_AUTHENTICATION']),'digest')===0)
$digest = substr($_SERVER['HTTP_AUTHORIZATION'], 7);
}
return $digest;
}
// This function forces a login prompt
function requireLogin($realm, $nonce) {
$cabecalho = 'WWW-Authenticate: Digest realm="' . $realm . '",'.
' qop="auth", nonce="' . $nonce . '", '.
'opaque="' . md5($realm) . '"';
header('HTTP/1.0 401 Unauthorized');
header($cabecalho);
echo 'Cancelado';
die();
}
// This function extracts the separate values from the digest string
function digestParse($digest) {
// protect against missing data
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
preg_match_all('@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@', $digest, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[2] ? $m[2] : $m[3];
unset($needed_parts[$m[1]]);
}
return $needed_parts ? false : $data;
}
//Analyse 401 header got from server and makes the parameters to
//setCredentials method of nusoap client
function getDigestToServer($url) //Used by client.php script, above
{
//Try to open the URL (read-only) - we are expecting this to fail because it is in the secured area
$fp = @fopen($url, 'r');
// Check response header from the server
if (isset($http_response_header))
{
// is it the 401 error we are expecting?
if (preg_match("@HTTP/[\d\.]+ 401@", $http_response_header[0]))
{
// recover the digest parameter string
for ($i = count( $http_response_header ) - 1; $i >= 0; $i-- )
{
if (strncasecmp('WWW-Authenticate', $http_response_header[$i], 16 ) == 0 )
{
$wauth = $http_response_header[$i];
$wauth = preg_replace("/^.+Digest /","",$wauth);
$wauthkeys = explode(",",$wauth);
$dgheaders = array();
foreach($wauthkeys as $seg) {
list($key,$val) = explode("=",$seg);
$val = preg_replace("/\"/","",$val);
$dgheaders[trim($key)] = $val;
}
return $dgheaders;
break;
}
}
die( 'Error connecting: Não encontrado "WWW-Authenticate"');
}
else
die( '2-Error connecting: ' . $http_response_header[0]);
}
else
die( '3-Error connecting: Bad URL, timeout, etc.');
}
?>
|
|