I'm trying to consume a .NET 2.0 web service using Axis.
I generated the web services client using Eclipse WST Plugin and it seems ok so far.
Here the expected SOAP header:
<soap:Header>
<Authentication xmlns="http://mc1.com.br/">
<User>string</User>
<Password>string</Password>
</Authentication>
</soap:Header>
I didn't find any documentation on how to configure this header from an Axis client.
When I generated the client using Visual Studio C# Express 2008, it generates a class named Authentication with two String attributes (User and Password) and all the client methods receive an object of this class as first parameter, but it did not happen with Axis WS client.
How can I set this header in my client calls?
Maybe you can use org.apache.axis.client.Stub.setHeader method? Something like this:
MyServiceLocator wsLocator = new MyServiceLocator();
MyServiceSoap ws = wsLocator.getMyServiceSoap(new URL("http://localhost/MyService.asmx"));
//add SOAP header for authentication
SOAPHeaderElement authentication = new SOAPHeaderElement("http://mc1.com.br/","Authentication");
SOAPHeaderElement user = new SOAPHeaderElement("http://mc1.com.br/","User", "string");
SOAPHeaderElement password = new SOAPHeaderElement("http://mc1.com.br/","Password", "string");
authentication.addChild(user);
authentication.addChild(password);
((Stub)ws).setHeader(authentication);
//now you can use ws to invoke web services...
If you have an object representing the Authentication container with userid and password, you can do it like so:
import org.apache.axis.client.Stub;
//...
MyAuthObj authObj = new MyAuthObj("userid","password");
((Stub) yourServiceObject).setHeader("urn://your/name/space/here", "partName", authObj);
I have the same issue and solved by the below fragement:
ServiceSoapStub clientStub = (ServiceSoapStub)new ServiceLocator().getServiceSoap(url);
org.apache.axis.message.SOAPHeaderElement header = new org.apache.axis.message.SOAPHeaderElement("http://www.abc.com/SSsample/","AuthHeader");
SOAPElement node = header.addChildElement("Username");
node.addTextNode("aat");
SOAPElement node2 = header.addChildElement("Password");
node2.addTextNode("sd6890");
((ServiceSoapStub) clientStub).setHeader(header);
I used almost the same solution as mentioned before:
SOAPHeaderElement cigWsHeader = new SOAPHeaderElement("https://ws.creditinfo.com", "CigWsHeader");
cigWsHeader.addChildElement("UserName").setValue("username");
cigWsHeader.addChildElement("Password").setValue("password");
var port = new ServiceLocator().getServiceSoap(someUrl);
((Stub) port).setHeader(cigWsHeader);
And spent hours searching why "Security header not found". And the aswer is... redundant symbol "/" at the namespace: "https://ws.creditinfo.com/" . Seriously! Keep it in mind.
Related
Just generated Java code from WSDL using Apache Axis 2. The service is protected with basic authentication. When I try to create authentication object in order to set the username and password, the class (HttpTransportProperties.Authenticator) is not found in the library.
How can I set basic authentication for the client code generated by Apache Axis2?
Here is the old way of setting basic authentication params:
HttpTransportProperties.Authenticator basicAuth = new HttpTransportProperties.Authenticator();
basicAuth.setUsername("username");
basicAuth.setPassword("password");
basicAuth.setPreemptiveAuthentication(true);
final Options clientOptions = stub._getServiceClient().getOptions();
clientOptions.setProperty(HTTPConstants.AUTHENTICATE, basicAuth);
stub._getServiceClient().setOptions(clientOptions);
I had the same Problem!
Solution: Use HttpTransportPropertiesImpl instead of HttpTransportProperties.
org.apache.axis2.client.OperationClient _operationClient = _serviceClient.createClient(_operations[1].getName());
_operationClient.getOptions()
.setAction("http://asdf/checkOutRequest");
HttpTransportPropertiesImpl.Authenticator basicAuth = new HttpTransportPropertiesImpl.Authenticator();
basicAuth.setUsername("tomcat");
basicAuth.setPassword("tomcat");
basicAuth.setPreemptiveAuthentication(true);
final Options clientOptions = _operationClient.getOptions();
clientOptions.setProperty(HTTPConstants.AUTHENTICATE, basicAuth);
_operationClient.setOptions(clientOptions);
For anybody needing a even more explicit example of uwesch's very helpful answer.
I have a java application that interacts with a SOAP service. I used the WSDL to generate a java client via CXF, but I need to authenticate my calls using ws-security. I am looking for a code-only way to do this, and I don't have any xml configurations. This is what I have tried:
Map ctx = ((BindingProvider)port).getRequestContext();
ctx.put("ws-security.username", "joe");
ctx.put("ws-security.password", "joespassword");
port.makeSoapCall();
But I get a parse error for invalid WS-Security header. What is the right way to do this?
In SOAP UI, I can do this easily by right-clicking the soap header, clicking "Add WSS UsernameToken", and selecting "Password Text"
You are using WS-SecurityPolicy as per the code you shared. How about using WS-Security only and sending across the usernametoken using WSS4JOutInterceptor?
Check the section "Adding the interceptors via the API" in apache cfx ws-security guide here : http://cxf.apache.org/docs/ws-security.html
This is what needs to be done as per the above apache cxf documenation above. You might only need the out interceptor path.
On the client side, you can obtain a reference to the CXF endpoint using the ClientProxy helper:
import org.apache.cxf.frontend.ClientProxy;
...
GreeterService gs = new GreeterService();
Greeter greeter = gs.getGreeterPort();
...
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(greeter);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
Now you're ready to add the interceptors:
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
...
Map<String,Object> inProps = new HashMap<String,Object>();
... // how to configure the properties is outlined below;
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
cxfEndpoint.getInInterceptors().add(wssIn);
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put("action", "UsernameToken Timestamp");
outProps.put("passwordType", "PasswordDigest"); //remove this line if want to use plain text password
outProps.put("user", "abcd");
outProps.put("passwordCallbackClass", "demo.wssec.client.UTPasswordCallback");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
You will need to write password callback class (UTPasswordCallback) in the example above.
Apache cxf has a complete sample for UserName token here: http://svn.apache.org/repos/asf/cxf/trunk/distribution/src/main/release/samples/ws_security/ut/
From the above link browse to client folder (src/main/java/demo/wssec/client) for user name token and UTPasswordCallback code.
EDIT: If your wsdl expects password as plain text then just remove this line from the code:
outProps.put("passwordType", "PasswordDigest");
You could take a look at the "ws-security/ut" demo that ships with CXF, this shows how to add a UsernameToken programmatically. Here is the client code:
https://github.com/apache/cxf/blob/master/distribution/src/main/release/samples/ws_security/ut/src/main/java/demo/wssec/client/Client.java
Colm.
<soapenv:Header>
<UsernameToken xmlns="http://siebel.com/webservices">uname</UsernameToken>
<PasswordText xmlns="http://siebel.com/webservices">pass</PasswordText>
<SessionType xmlns="http://siebel.com/webservices">None</SessionType>
</soapenv:Header>
I have generated client code using axis runtime and I am getting this exception:Operation 'QueryByExample' with no authentication cannot be executed in an anonymous session pool. Please associate an authentication type with the web service operation.(SBL-EAI-04552).
I looked at others answers from stackoverflow for hours and nothing worked out for me. Please guide me....
Service code:
SOAPHeaderElement wsseSecurity = new SOAPHeaderElement(new PrefixedQName("http://schemas.xmlsoap.org/ws/2002/04/secext","Security", "wsse"));
MessageElement username = new MessageElement("uname", "UsernameToken");
MessageElement password = new MessageElement("pass", "PasswordText");
username.setObjectValue("username");
password.setObjectValue("password");
wsseSecurity.addChild(username);
wsseSecurity.addChild(password);
stub.setHeader(wsseSecurity);
You need to add few more things and the main problem is how you are deifning and using your password. You are on the correct path but here is how you would make a SOAP Axis 1.4 client:
InputStream inConfig = BaseTestCase.class.getClassLoader().getResourceAsStream("axis_client_config.xml");
EngineConfiguration config = new FileProvider(inConfig);
PartnerAPILocator locator = new PartnerAPILocator(config);
inConfig.close();
stub = locator.getSoap();
Stub axisPort = (Stub) stub;
axisPort._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
axisPort._setProperty(WSHandlerConstants.USER, "ET USERNAME");
axisPort._setProperty(WSHandlerConstants.PW_CALLBACK_REF, new PasswordTokenHandler());
here is my source and try to follow the tutorial and you can even download the code. Hope this helps you.
I have been provided a WSDL for a webservice. I am now required to digitally sign that request. The previous developer utilized the Eclipse feature to generate proxy classes. Add the WSDL to the project, then right click on it, click "Web Service", then "Generate Client".
This worked fine until we were required to digitally sign the request. I did some digging and it looks like Axis 1.4 doesn't allow you to sign requests. You can use WSS4J to do that. I mavened in WSS4j 1.5 into my project.
I'm at a loss on how to digitally sign the request. Here is my existing code that uses the proxy classes:
XiSecureWSServiceLocator service = new XiSecureWSServiceLocator();
service.setXiSecureWSServicePortEndpointAddress(paymetricPortAddress);
XiSecureWSPortType proxy = service.getXiSecureWSServicePort();
((Stub) proxy).setTimeout(paymetricTimeOutinMillisec);
SDecrypt_InputType sdi = new SDecrypt_InputType();
sdi.setStrToken(ccNumber);
sdi.setStrUserID(user);
SDecrypt_OutputType sdo = null;
sdo = proxy.pm_SingleDecrypt(sdi);
What I want to do is something similar to this article. Here is a function they used:
public Message signSOAPEnvelope(SOAPEnvelope
unsignedEnvelope) throws Exception
{
WSSignEnvelope signer = new WSSignEnvelope();
String alias = "16c73ab6-b892-458f-abf5-2f875f74882e";
String password = "security";
signer.setUserInfo(alias, password);
Document doc = unsignedEnvelope.getAsDocument();
Document signedDoc = signer.build(doc, crypto);
// Convert the signed document into a SOAP message.
Message signedSOAPMsg =
(org.apache.axis.Message)AxisUtil.toSOAPMessage(signedDoc);
return signedSOAPMsg;
}
How can i get the Soap Envelope to be signed when all of the code to create it is hidden in the generated proxy classes?
This JavaRanch Thread explains implementing Security and Encryption with WSS4J using Axis handlers.
It looks like you have to do a number of things:
Configure/write a wsdd
Call the web service with an EngineConfiguration pointing to your wsdd file
Write a password callback class
Write a crypto.properties file
ensure the crypto.properties file and the key store containing the certificate are on the class path of the app.
Props to John Farrel on the JavaRanch forum for figuring all this out.
All in all kind of a pain in the butt. If there's a way to obtain the underlying SOAP Message itself from the Axis proxy class, that might be a quicker way to do it, but I don't have a lot of experience with Axis 1.
Hello from /r/java, by the way!
Found this:
Can anyone recommend to me or point me somewhere that describes
a simple, straightforward way to sign a SOAP request with a Digital
Signature within the Axis framework?
"Have a look at the WSS4J project. They provide Axis handlers for signing and encrypting as it is described in WS Security."
http://mail-archives.apache.org/mod_mbox/axis-java-user/200403.mbox/%3CCGEOIPKACAGJDDPKCDIHEEKACCAA.abhinavm#contata.co.in%3E -
Does that help?
I have registered my web application for use with oath2 using the following instructions:
http://code.google.com/apis/accounts/docs/OAuth2.html
This means my client is created with a client ID, client secret and Redirect URI.
Once I have configured my web application as per
http://code.google.com/apis/accounts/docs/OAuth2WebServer.html
I recieve a code in a request parameter from google, which I can then use to request an access token, which comes in a JSON in a format along the lines of:
{
"access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
"expires_in":3920,
"token_type":"Bearer"
}
Once this is done, I can use that access token to access a google api on behalf of the user:
GET https://www.googleapis.com/oauth2/v1/userinfo?access_token=1/fFBGRNJru1FQd44AzqT3Zg
This as documented is done by simply passing the access token as a request parameter.
However when I move onto using a Java API (In this case google contacts) I get the following in the documentation for HMAC-SHA1:
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET);
oauthParameters.setOAuthToken(ACCESS_TOKEN);
oauthParameters.setOAuthTokenSecret(TOKEN_SECRET);
DocsService client = new DocsService("yourCompany-YourAppName-v1");
client.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
URL feedUrl = new URL("https://docs.google.com/feeds/default/private/full");
DocumentListFeed resultFeed = client.getFeed(feedUrl, DocumentListFeed.class);
for (DocumentListEntry entry : resultFeed.getEntries()) {
System.out.println(entry.getTitle().getPlainText());
}
Or the following for RSA-SHA1
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET);
oauthParameters.setOAuthToken(ACCESS_TOKEN);
PrivateKey privKey = getPrivateKey("/path/to/your/rsakey.pk8"); // See above for the defintion of getPrivateKey()
DocsService client = new DocsService("yourCompany-YourAppName-v1");
client.setOAuthCredentials(oauthParameters, new OAuthRsaSha1Signer(privKey));
URL feedUrl = new URL("https://docs.google.com/feeds/default/private/full");
DocumentListFeed resultFeed = client.getFeed(feedUrl, DocumentListFeed.class);
for (DocumentListEntry entry : resultFeed.getEntries()) {
System.out.println(entry.getTitle().getPlainText());
}
First off, it seems that if I was doing standard http rather than the java wrapper, all I would need to provide is an access token. Am I missing something or where have these additional parameters come from? Mainly TOKEN_SECRET, which there is no mention of in the docunentation. There is also no mention of having to provide CONSUMER_KEY and CONSUMER_SECRET. I am presuming they are alternative names for client id and client secret, but I do not understand why I am now having to provide them. Finally when setting up my application using the google API's console, there was no mention whatsoever of the two different encryption types, and which one I am going to be using, am I missing something here aswell?
The Java code examples you show are based on OAuth 1.0 (not OAuth 2.0) which has some crypto requirements which were simplified in OAuth 2.0. In some cases with the Google Contacts API you need OAuth 1.0. See: http://code.google.com/apis/contacts/docs/3.0/developers_guide.html#GettingStarted