PHP stream_context_create with proxy - php

I'm currently developing an web application which uses an XML Interface located on a different server, that I have to access via a proxy.
So I tried to set the proxy in a stream_context_create array, but it doesn't seem to work.
$set = array(
'http' => array(
'method' => 'GET',
'header' => sprintf(
'Proxy-Authorization: Basic %s',
base64_encode(Constants::XML_AUTH)
),
'protocol_version' => '1.1',
'proxy' => '89.122.180.178:46565'
)
);
$stream = stream_context_create($set);
I'm not quite sure what I'm doing wrong.
If I comment out the proxy key i get a 403 Forbidden Response as it should be.
If I comment in the proxy key I receive a 400 Bad Request Response.
I'm not quite sure what I'm doing wrong. Can you help me out? I never did a communication through a proxy before with PHP.

My guess is that the proxy declaration is missing the protocol. An URI has to be specified (according to the doc), that contains the protocol (scheme).
So this could work: 'proxy' => 'tcp://89.122.180.178:46565'. It might be necessary to remove 'protocol_version' since this may not be required for tcp.
Does that work for you? (or have you already solved it? ... ;-)

Related

PHP SoapClient Doesn't Retrieve WSDL with Client Certificate

Other similar questions have not helped me resolve this.
I have to retrieve a WSDL file using a client certificate + private key combination from my webserver calling another external SOAP API.
$wsdl = 'https://www.example.com?wsdl';
$endpoint = 'https://www.example.com';
$sslContext = stream_context_create($contextOptions);
$options = [
'local_cert' => '/var/www/combo.pem',
'passphrase' => 'Pass1',
'cache_wsdl' => WSDL_CACHE_MEMORY,
'trace' => 1,
'stream_context' => stream_context_create([
'ssl' => [
'ciphers' => 'RC4-SHA',
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
])
];
try{
$soapClient = new SoapClient($wsdl, $options);
}
catch(Exception $e)
{
var_dump($e);
}
The error I'm getting is:
SOAP-ERROR: Parsing WSDL: Couldn't load from '..domain..' : failed to load external entity "..domain..?wsdl"
I tried numerous settings and none of them made any difference to this response. I tried no settings, empty array.
What has worked:
Establishing a raw connection via CURL, so the certificate file is fine
Retrieving WSDL information from SoapUI, so the WSDL destination is correct and the certificate file was okay
phpinfo() returns SoapClient is enabled, OpenSSL is enabled. What else could I try or check?
SOAP error could come from invalid character encoding or maybe some HTTP header missing like 'User-Agent' when you query the remote server.
Try to adding User-Agent to options like the sample below.
$options = array(
'http' => array(
'user_agent' => 'PHP_Embedded_Soap_Client'
)
);
PS: I would not recommend to strict ciphers to: RC4-SHA
I wanted to comment this but based on others' suggestions of using file_get_contents and your reply mentioning that it returned false, I'm now kind of sure it's more of a connection problem. Please check followings:
It's obvious that your actual $wsdl value is different than what is posted but please make sure that .com?wsdl is not happening in your code. it should be .com/?wsdl.
Check your DNS settings. A lookup through dnslookup can help identify problem.
Make sure date & time setting of server is correct. It can lead to SSL errors.
If none of above helped. You might consider downloading WSDL content with other tools (such as cURL) and on different machines to identify the cause of problem.

GET works but POST doesn't for silent login

We have 2 systems one in PHP and one in asp.net which currently require separate logins even though both use the same username/password information.
As a quick (and temporary) fix I thought I might be able to amend the PHP login page to pass the login details to the asp.net page behind the scenes so the user could be logged in automatically to both systems rather than having to enter their credentials again when navigating to a different page.
This works fine when I use a GET to pass the parameters but of course the GET parameters including the password get stored in the server log which is not a good idea.
So I would like to use POST instead, but I can't get it to work. I used the CURL-less method in How do I send a POST request with PHP? (code below) and it appears to work but the asp.net login process creates secure cookies and while they are stored if I GET the page they are not being stored when I POST to it instead.
$url = 'https://server.com/path';
$data = array('key1' => 'value1', 'key2' => 'value2');
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
var_dump($result);
I have tried something similar with CURL in the past so I know that CURL creates it's own browser context but I thought a straight POST request would work, however it seems to be behaving much the same as CURL.
Is there some way to get this to work or do I have a fundamental misunderstanding of how POST works? If so could somebody point me at a good explanation.

Writing library for Twitter, where am I going wrong?

I'm writing a library to connect to Twitter that uses Requests for PHP. I'm not sure, but I don't think that I'm building the OAuth correctly because I can't authenticate. I've double-checked it, and checked it against another existing library but still can't seem to get it right.
The code is here.
The idea is you instantiate the service, send it config parameters, and before it does the request, it generates the 'Authorization: OAuth xxx' header and adds it to said request.
$twitter = array(
'consumer_key' => '',
'consumer_secret' => '',
'access_token' => '',
'access_token_secret' => '',
'screen_name' => '_hassankhan',
'api_url' => 'https://api.twitter.com/1.1/'
);
$service = new OAuth1AService('Twitter', $twitter['api_url']);
$service->config($twitter);
$service->doGet(
'statuses/user_timeline.json',
array(
'screen_name' => '_hassankhan',
'include_entities' => 'true'
),
array(),
'raw'
);
print($service->getResult());
I would really recommend you to use one of the already made libraries like tmhOAuth which make it really easy to interact with the twitter api.
As for your problem, seems you don't sign your request correctly. At least I could not easily find out if you include all request parameters to create the signature.
The oauth_signature parameter contains a value which is generated by
running all of the other request parameters and two secret values
through a signing algorithm.
Creating the signature is described in this document: https://dev.twitter.com/docs/auth/creating-signature .

Using a proxy server with fopen

I'm trying to use fopen to read a remote file from another website. I want to use a proxy to do this, and as far as I know I can do:
$context = stream_context_create(array(
'http' => array(
'proxy' => 'tcp://192.168.10.10:80' // The proxy server address and port
),
));
$file = fopen($url, 'r', false, $context)
but is there a way to authenticate using a username and password for that proxy? Or am I limited to having to use public proxies?
Also, the proxy definition is tcp://192.168.10.10:80. If I wanted to use a HTTP proxy, am I free to just change it to http://192.168.10.10:80?
Thanks.
You can use the Proxy-Authorization in the $context if the proxy requires authentication.Example from PHP.Net:
$opts= array(
'http' => array(
'proxy' => 'tcp://proxyip:8080',
'header' => array(
"Proxy-Authorization: Basic $auth"
)
)
);
$context = stream_context_create($opts);
Also,I think you cannot change tcp to http in tcp://192.168.10.10:80 since what the proxy does is establishing a TCP connection to another server on behalf of a client then route all the traffic back and forth between the client and the server.Obviously it concerns with TCP(sometimes UDP) instead of HTTP.Http proxies just "understand" the traffic delivered by HTTP protocol.

Windows Azure Authentication for Bing Search in PHP

I am trying to perform a Bing Search by using the Windows Azure Marketplace API, I have downloaded their guide and sample code. The code prepares a HTTPS request with basic authentication, however I am constantly getting the following error:
Warning: file_get_contents(https://api.datamarket.azure.com/Data.ashx/Bing/SearchWeb/Web?Query=%27washburn%27&Adult=%27Off%27&$top=50&$format=Atom): failed to open stream: Connection refused
The php code (from Microsoft's document):
$context = stream_context_create(array(
'http' => array(
'proxy' => 'tcp://127.0.0.1:8888',
'request_fulluri' => true,
'header' => "Authorization: Basic " . base64_encode($accountKey.":".$accountKey)
)
));
Does anyone know what is causing the error please? I have correctly set the $accountKey and I tested it in a browser. What puzzles me a little is 127.0.0.1:8888 and also base64_encode($accountKey.":".$accountKey) , how come you need the $accountKey both before and after the : while when using a browser you are supposed to leave the username blank and just input the account key into the password field?
I have solved it and here is what I have found for future people that would be doing the same thing:
I commented out the line where it says:
'proxy' => 'tcp://127.0.0.1:8888',
'request_fulluri' => true,
and also set base64_encode("ignored:".$accountKey) instead
Base on what I read on MSDN, the username part is said to be ignored, so it shouldn't matter what value it is. I was thinking perhaps the length or the special characters in the key screwed things up so I replaces it with ignored (or anything really).
That did the trick and I can parse the returned JSON data. Good luck!

Categories