I have a service provider that requires a non-standard Authorization Type for their web service.
Instead of Basic, Digest, NTLM, etc., they require "Basic API Access.".
I have tried the code below and used Fiddler to check the web service request.
It does not seem that any custom strings can be used
Binding avail = new Binding();
avail.Url = "https://amer.webservicesxx.com/Availability";
NetworkCredential netCredential = new NetworkCredential("abc", "def");
Uri uri = new Uri(avail.Url);
CredentialCache cred = new CredentialCache();
cred.Add(uri, "Basic API Access", netCredential);
avail.Credentials = cred;
SearchRsp response = avail.service(request);
POST https://amer.webservicesxx.com/Availability HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client
Protocol 4.0.30319.1) VsDebuggerCausalityData:
uIDPo+CJPwpspBxKp939c... Content-Type: text/xml; charset=utf-8
SOAPAction: "" Host: america.webservicesxx.com Content-Length:
658 Expect: 100-continue
?xml version="1.0" encoding="utf-8"?> ?soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/20 01/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> ...
?/soap:Envelope>
It is missing the ...
Authorization: Basic API Access/dUFQSS04NDA0NTk2MDk6WiFyYzBuZDg0...
...line in the header.
If I just use "Basic" it adds the Authorization line properly, but is rejected by the service provider.
Is this the correct syntax to add an Authorization: header to the Soap transaction?
I needed to replace data in the web request.
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
WebRequest request = base.GetWebRequest(uri);
request.Headers.Add("Authorization: Basic API Access dUFQSS04NDA0NT...");
return request;
}
inside the web service reference class.
Related
I have a request post the send in acunetix scanner , but don't know how to send it and how to specify the post method , because when i added the headers in the "custom headers" option in acunetix scanner i got the get method sendded instead of the post one .
This is my request to send:
POST /Test/new_date HTTP/1.1
Host: app-test-ext
Content-Type: application/json
Cache-Control: no-cache
{UserName:test01,Password:poper}
We connect with multiple (20-30) third-party web services within our C# Batch Application. We are attempting to find the best way to call these web services dynamically (without generating proxy or using wsdl). All the third party agencies endpoints or URL's will be configured in database table. Client app will check the URL at run-time and make a service call. We are not worried about async calls it’s all synchronized process.
SQL Table : Client-configuration
Client URL Method IsActive
A http://serverhost/ClientA/Service1.svc Submit 1
B http://serverhost/ClientB/Service2.asmx Submit 1
The only issue is we are not sure about the third party service implementation is WCF or asmx. I have read few articles online to use HttpWebRequest to call web services dynamically (without generating proxies/wsdl.)
Is this the best way to implement this or any concerns I need to think of?
Please see below ex:
public static void CallWebService(string xml)
{
var _Url = "http://serverhost/ClientA/Service1.svc";
var _action = "http://serverhost/ClientA/Service1.svc/Submit";
try
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] data = encoder.GetBytes(xml);
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(xml);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_Url);
webRequest.Headers.Add("SOAPAction", _action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.ContentLength = data.Length;
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
Stream webStream = webRequest.GetRequestStream();
webStream.Write(data, 0, data.Length);
webStream.Close();
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
using (StreamReader sr = new StreamReader(responseStream))
{
string s = sr.ReadToEnd();
}
}
catch (Exception ex)
{
responseStream = ex.Response.GetResponseStream();
}
}
Here is the details shared by one of the client.
http://setup.localhost.com/ClientA/Service1.asmx
Operation : Submit
SOAP 1.1
The following is a sample SOAP 1.1 request and response. The placeholders shown need to be
replaced with actual values.
POST /ClientA/Service1.asmx HTTP/1.1
Host: setup.localhost.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://setup.localhost.com/Submit"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Submit xmlns="http://setup.localhost.com/">
<eCitXML>string</eCitXML>
<eCitPdf>base64Binary</eCitPdf>
<eCitKey>string</eCitKey>
</Submit>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SubmitResponse xmlns="http://setup.localhost.com/">
<SubmitResult>string</SubmitResult>
</SubmitResponse>
</soap:Body>
</soap:Envelope>
SOAP 1.2
The following is a sample SOAP 1.2 request and response. The placeholders shown need to be
replaced with actual values.
POST /ClientA/Service1.asmx HTTP/1.1
Host: setup.localhost.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-
envelope">
<soap12:Body>
<Submit xmlns="http://setup.localhost.com/">
<eCitXML>string</eCitXML>
<eCitPdf>base64Binary</eCitPdf>
<eCitKey>string</eCitKey>
</Submit>
</soap12:Body>
</soap12:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-
envelope">
<soap12:Body>
<SubmitResponse xmlns="http://setup.localhost.com/">
<SubmitResult>string</SubmitResult>
</SubmitResponse>
</soap12:Body>
</soap12:Envelope>
I think your question could be rephrased as
Is there a generic method to call any SOAP 1.1 or 1.2 web service operation without prior knowledge of the service operation except for the SOAP action and URL?
I'm assuming that all the third party web services expose a common operation which accepts and returns the same types.
If this is the case then providing you model the service operation contract correctly you could use ChannelFactory to call all the services.
Calling WCF services is straightforward in this manner, but to call asmx services you'd need to do a bit more work. So your client code would need to know if the service was asmx or wcf, and moreover, if wcf, whether the service is soap 1.1 or 1.2.
I must say I'm struggling to understand what advantage you will have once you have achieved this. I can see the value if you owned all the 20+ services you were calling, but this clearly is not the case.
Granted, you won't have a ton of nasty generated service reference code, but the whole point of WSDL is it allows for machine generated service contracts. If the third party services make any breaking changes you'll need to manually synchronize these inside your client code, rather than just regenerating the client.
So I have mapped a WSO2 DSS service through WSO2 ESB. I have generated a jax-ws client and I am using it successfully to get some data.
The problem is that sometimes when I call the client it throws a
Exception in thread "main" java.lang.NullPointerException
at com.sirmaitt.egov.codelist.client.Client.main(Client.java:77)
At that line of the source code I am trying to print the response data in the console.
Here's the code I'm using to call the service
// Initialize service
Codelists_Service service = new Codelists_Service();
// Adds custom handler so we can add custom SOAP security header.
service.setHandlerResolver(new HandlerResolver() {
#SuppressWarnings("rawtypes")
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlers = new ArrayList<Handler>();
handlers.add(new SecuritySOAPHandler());
return handlers;
}
});
CodelistsPortType port = service.getCodelistsHttpsSoap11Endpoint();
Codelists codelists = null;
try {
codelists = port.getcodelists();
} catch (DataServiceFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Prints the response.
for (Codelist cList : codelists.getCodelist()) {
}
Rest of the project are mainly jax-ws generated classes and one custom SOAPHandler, which I use to add a security header.
The issue is that this same client actually starts working when I log in the WSO2 ESB and click on the service I've mapped there. And it throws exception when I don't use the service for some time.
This issue really puzzles me. What can be the cause of it?
EDIT: Clarification, the code on line 77 is the for loop. It seems the codelists object is null.
EDIT: Here's the method that adds the security header to the request.
public boolean handleMessage(SOAPMessageContext messageContext) {
Boolean isOutboundMessage = (Boolean) messageContext
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (isOutboundMessage) {
SOAPPart messageSoapPart = messageContext.getMessage()
.getSOAPPart();
WSSecHeader securityHeader = new WSSecHeader();
securityHeader.insertSecurityHeader(messageSoapPart);
WSSecUsernameToken usernameToken = new WSSecUsernameToken();
usernameToken.setPasswordType(WSConstants.PASSWORD_TEXT);
usernameToken.setUserInfo(USER_NAME, PASSWORD);
WSSecTimestamp timestamp = new WSSecTimestamp();
usernameToken.build(messageSoapPart, securityHeader);
timestamp.build(messageSoapPart, securityHeader);
}
return true;
}
And here is what the request looks like (taken from console)
---[HTTP request]---
SOAPAction: "urn:_getcodelists"
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Type: text/xml;charset="utf-8"
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" S:mustUnderstand="1"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-11800260"><wsu:Created>2012-09-18T13:17:56.707Z</wsu:Created><wsu:Expires>2012-09-18T13:22:56.707Z</wsu:Expires></wsu:Timestamp><wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-9299042"><wsse:Username>admin</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">admin</wsse:Password></wsse:UsernameToken></wsse:Security></S:Header><S:Body></S:Body></S:Envelope>--------------------
---[HTTP response 202]---
Transfer-encoding: chunked
null: HTTP/1.1 202 Accepted
Connection: keep-alive
Server: Synapse-HttpComponents-NIO
Date: Tue, 18 Sep 2012 13:19:57 GMT
I think it is because your session timed out and you needed to log in again to authenticate the service.
I'm trying to connect to a https web service (not .NET as far as I know).
I can't control the other side in any way, I just got some standards and a wsdl to operate
with it.
I have created at first the client using Add Service Reference, tried some things until I get through some problems, where one most serious was that I couldn't add the Authentication header to the message which was resulting in fail.
Added the service using old Add Web Reference and seemed more easily managed and appropriate, using a partial class and override the GetWebRequest, I added this code so I can preauthenticate with the service and add the security header, which they don't mention in the wsdl link. I know that it is not mandatory for services to tell this but it would be nice my Web Service creators fellow developers.
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
if (PreAuthenticate)
{
NetworkCredential networkCredentials = Credentials.GetCredential(uri, "Basic");
if (networkCredentials != null)
{
byte[] credentialBuffer = new UTF8Encoding()
.GetBytes(networkCredentials.UserName + ":" + networkCredentials.Password);
request.Headers["Authorization"] = "Basic" + Convert.ToBase64String(credentialBuffer);
}
else
{
throw new ApplicationException("No network credentials");
}
}
return request;
}
To call the service I added this code:
using (Service client = new Service()) // autogenerated Service class
{
client.EnableDecompression = true;
// Create the network credentials and assign
// them to the service credentials
NetworkCredential netCredential = new NetworkCredential("test1", "test1");
Uri uri = new Uri(client.Url);
ICredentials credentials = netCredential.GetCredential(uri, "Basic");
client.Credentials = credentials;
// Be sure to set PreAuthenticate to true or else
// authentication will not be sent.
client.PreAuthenticate = true;
// Make the web service call.
Request req = new Request { UserName = "test2", Password = "test2"; // an object created from autogenerated code
RequestResult result = client.processMessage(req); // autogenerated code
}
While testing this call and checking with fiddler my request. I see 2 calls a keep alive call with these header, nothing special.
CONNECT server:443 HTTP/1.1
Host: server
Connection: Keep-Alive
Sending 570 returning a 200 result.
HTTP/1.1 200 Connection Established
FiddlerGateway: Direct
StartTime: 00:05:13.743
Connection: close
And the call with the data sending 571 result 500 error:
POST /host/Service HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.5448)
Authorization: BasicdXNlcOTc3MzQyMGTDFTR4dftfrdg5 // changed this hash for security reasons
VsDebuggerCausalityData: // Removed this hash for security reasons
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Host: server-host-url
Content-Length: 7238
Expect: 100-continue
Accept-Encoding: gzip
Connection: Keep-Alive
The error exception in .NET client:
Error on verifying message against security policy Error code:1000
As you see the Authorization header exist. I also tried with adding a space after Basic you can see above where exactly in the overriden method, and seemed fiddler recognized it better and also decoded the username:password header.
This results into that response:
HTTP/1.1 500 Internal Server Error
Date: Sat, 21 Apr 2012 21:05:22 GMT
Server: Oracle-Application-Server-11g
X-Powered-By: Servlet/2.5 JSP/2.1
X-Cnection: close
Transfer-Encoding: chunked
Content-Type: text/xml;charset="utf-8"
Content-Language: en
X-Pad: avoid browser bug
Set-Cookie: BIGipServerpoolXoas243_254_9999=437682499.99988.0000; path=/
The strange thing I wonder first is if the first call should be preauthenticated, the handshake keep alive one? This 500 error I know that causes when authentication header is not present, but mine is. Preauthentication is what I need to know how it should happen and I guess it's not working if it should appear in the 1st message.
Another strange thing is that if I change the 2 pairs of passwords opposite, I see on fiddler that I get 3 messages, 1 with the handshake and result in 200 and "TWO" others with 401 Authorization Required.
This drives me crazy. Any help appreciated to save my soul.
Thank you!
I am trying to set cookie from client using below code snippet, I am using JAXWS RI 2.2.3.
Map<String, Object> ctxt = ((BindingProvider) portType).getRequestContext();
Map<String, List<String>> httpHeaders = new HashMap<String, List<String>>();
httpHeaders.put("Content-Encoding", Collections.singletonList("gzip"));
httpHeaders.put("Cookie", Collections.singletonList(cookie));
ctxt.put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);
From the SOAP log I see that Cookie is not getting set, but it's set in the context header.
Any other header is getting set except Cookie and I am not able to find out the reason.
I need to get a session from one service and set it to another service to work with it, but I am not able to do so here.
HTTP headers: {Cookie=[mysession="529fc605-8188-7f3b-21ad-92407976d5a9";], Accept-Encoding=[gzip], Content-Encoding=[gzip]}
---[HTTP request - https://10.112.83.155:443/eam/sdk/]--- Accept: text/xml, multipart/related Accept-Encoding: gzip Content-Encoding: gzip Content-Type: text/xml; charset=utf-8 [] Set-Cookie: vmware_soap_session="529fc605-8188-7f3b-21ad-92407976d5a9"; SOAPAction: "urn:internaleam/2.0" User-Agent: JAX-WS RI 2.2.3-b01-
This was a bug in JAX-WS. Bug link: JAX_WS-1044
Currently fixed in JAX-WS 2.2.7 which is not yet released.