My webservice uses soapsession as the session mechanism. I want to call that web service using ksoap2 api. How can I call that web service so that session will be maintained? ya, one more question. Now the web service is not returning the ServiceGroupId to the client written in ksoap2 api unlike it sends the same when I write the client using the axis2 api (ServiceClient). This is because in ksoap2 client, I am not engaging the addressing module. So, my question is Can I engage the addressing module using ksoap2 ?
You can use a KeepAliveHttpsTransportSE, but you can only use this one connection then.
Else you need to get the sessionID from your auth call.
When you have made the auth call with your HttpsTransportSE transport use this:
List<HeaderProperty> hp = (List<HeaderProperty>)transport.getConnection().getResponseProperties();
for (int i = 0; i < hp.size(); i++) {
if (hp.get(i).getKey().equals("set-cookie")){
SESSION_ID = hp.get(i).getValue();
break;
}
}
And set the sessionID into the header when you make a new WebService Call.
Related
I'm working with gSOAP 2.8.15 and I'm trying to implement the HTTP Authentication by following the instructions in section 19.14 of gsoap documentation (http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc19.14).
The only difference is that the codes introduced in the documentation is written in C but I'am coding in C++.
Here is my codes for client side of the web service
// The variable wsp is a instance of web service proxy generated by soapcpp2.
// The proxy is a sub-class of the class soap
wsp.userid = "user";
wsp.passwd = "password";
// call the function of web service
wsp.get_version(&result);
In the server side, I use these codes to check the authentication:
// The variable wss is the a instance of web service service generated by soapcpp2.
if (wss.userid == NULL || wss.passwd == NULL)
//......
The problem is when I call the function of web service using the client-side code, the userid and passwd is always NULL in server-side. But when I call the same function using soapUI by passing the userid and passwd with preemptive authorisation mode, the server will get the information without problem.
I appreciate if anyone can help me work out the problem. Thanks for your attention.
I have used tcpdump to catch the package sent between web service server and client and I found that there is no http header sent when the client call the function of the web service. So I have done some search in the documentation of gSOAP and found this sentence:
A client may use the http:// prefix. When absent, no HTTP header is
sent and no HTTP-based information will be communicated to the
service.
It solves my problem...
I need to have an activity that send a mail at a certain point of the BPEL process.
Is there a "mail activity" or do I have to code a sort of web services to invoke so that I call the service and let it send the mail?
Could it be a solution to use the ESB for this business?
How to connect the two (again with a web services or there is a quicker and easiest way to link them)?
Could it be a good solution in this case to add the ESB feature to BPS to add it the transport feature without having to add the ESB just for this?
Also I've seen that there are some example around that uses the transportSender in axis2.xml than using a proxy, but it seems that this method send the mail always to the same address I need to be able to send a mail to a subject (an possible cc and bcc) from parameters of the process (on a previous step I read data from DB and there is the address information) could the tensportSender be the path to follow or I have to develop the mailing service?
Any hint?
Thanks
Luca
As mentioned before, currently there is no mailing activity built-in for WSO2 BPEL, but you can get this functionality by invoking an external web service(DSS, AS) from inside the BPEL workflow.
I've created one workflow with such functionality couple days ago. Basically I created and Axis2 service that is just Java code for sending email, in which I can provide the parameters such as subject, content and receiver, so once you invoke the service you can send the email to any email address. I deployed the Axis2 service mentioned into a WSO2 DSS and invoke it from BPEL workflow that later on I deployed into WSO2 BPS.
The Java code I used for sendin the email is the following:
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class MailSender {
public static void main(String emailAddress, String content){
String host = "smtp.gmail.com";
String from = "example#gmail.com";
String subject = "Subject example";
Properties props = System.getProperties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.user", from);
props.put("mail.smtp.password", "");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth", "true");
try{
Session session = Session.getDefaultInstance(props, null);
InternetAddress to_address = new InternetAddress(emailAddress);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, to_address);
message.setSubject(subject);
message.setContent(content, "text/html; charset=UTF-8");
Transport transport = session.getTransport("smtp");
transport.connect("smtp.gmail.com","example#gmail.com","Password");
transport.sendMessage(message, message.getAllRecipients());
transport.close();
}
catch (MessagingException mex) {
System.out.println("send failed, exception: " + mex);
}
}
}
Currently, there is no mailing activity in BPS as a built-in activity.
But Yes, you can achieve your task by combining ESB and BPS. You can do it as follows.
First expose ESB email sending service as a proxy and then call that service using BPS. It is better to use a separate ESB for this task, since I have faced some difficulties when integrating ESB features into BPS.
I have two servlets that access two corresponding Axis2 web services on the same host. One of the servlets is read-only, while the other writes to a database.
Each of the Axis2 web services uses BASIC authentication. The read-only web service uses a system account, while the write web service uses the user's credentials (which are submitted as part of a web form).
The problem I'm running into is that the servlet called second always fails authentication to its web service. For example, I can query the read-only service through it's servlet all I want, but I get a "401: Authorization Required" when I try to use the write service. If I call the write service first, I get the same error when I try to use the read-only service.
Here is how I am setting the credentials for the connections in the servlets:
Stub service = new Stub(serviceUrl);
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);
auth.setPreemptiveAuthentication(true);
service._getServiceClient().getOptions().setProperty(HTTPConstants.AUTHENTICATE, auth);
The servlet that accesses the read-only service has this code in it's constructor. The servlet that accesses the write service has this code in it's doGet/doPost method.
It seems that the credentials for the first service called are getting cached somewhere, but I can't find where that could be. I saw a possible solution here, but I can't find where WSClientConstants.CACHED_HTTP_STATE is defined. The comments in this JIRA issue seems to imply that it's part of org.apache.axis2.transport.http.HTTPConstants but it's not there.
Specifics:
Axis version: 1.5.1
Tomcat Version: 6.0.26
Java version: 1.6.0_23
It turns out the connections to the two different services were using the same JSESSIONID. Thus, the connection to the second web service was trying to use a session authenticated for the first web service, causing the error.
My solution for this was to define an HttpClient for each service, done by the following
MultiThreadedHttpConnectionManager manager = new MuliThreadedHttpConnectionManager();
HttpClient client = new HttpClient(manager);
ConfigurationContext context = ConfigurationContextFactory.createDefaultConfigurationContext();
context.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, client);
context.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, true);
Stub service = new Stub(context, serviceUrl);
This allows both servlets to have a separate session for their corresponding services.
The important point is to create a dedicated ConfigurationContext.
I've solved in a simpler way using a default config context when creating the stub without the multithreaded connection factory
stub = new MyStub(ConfigurationContextFactory.createDefaultConfigurationContext(), myServicesUrl);
I have a standalone web-service client. When invoking any of the web-methods an additional "cookie" string must be implicitly(not as a web-method parameter) passed to the WS. The WS on the other end must be able to obtain the string and use it. How can this be achieved?
I invoke the service in the following way:
Service srv = Service.create(new URL(WSDL), QNAME);
myClassPort = srv.getPort(MyClass.class);
What I need is to put some code before the first line, which would make the client send this "cookie" string every time I invoke some remote method via myClassPort. Thx.
By default JAX-WS web services and clients are stateless. When a client makes a request, the server responds and sets a cookie on the connection, if it participates in a session. But, the JAX-WS client ignores that cookie and the server treats subsequent requests as new interaction. When the session is enabled, JAX-WS client sends the same cookie with each subsequent request so that server can keep track of the client session.
So you should not be using either cookies or HTTP sessions with web services. Return a token ID as part of the response; then the client can send that along with the next request.
Anyway:
JAX-WS web service clients must be configured to maintain session information (such as cookies), using the javax.xml.ws.session.maintain property.
Other web service stacks may have similar mechanisms.
On the Server Side
JAX-WS uses some handy annotations defined by Common Annotations for the Java Platform (JSR 250), to inject the web service context and declaring lifecycle methods.
WebServiceContext holds the context information pertaining to a request being served.
You don't need to implement javax.xml.rpc.server.ServiceLifecycle. With JAX-WS Web Service all you need to do is mark a field or method with #Resource. The type element MUST be either java.lang.Object or javax.xml.ws.WebServiceContext.
#WebService
public class HelloWorld {
#Resource
private WebServiceContext wsContext;
public void sayHello(){
MessageContext mc = wsContext.getMessageContext();
HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
}
}
There are some misleading answers to this question, so I will attempt to highlight current best practices. Most of these suggestions are part of the OWASP security guidelines, which I strongly recommend anyone working on web development to review.
1) ALWAYS use temporary (session scoped) cookies.
2) All cookies should be protected and encrypted.
3) Do not pass tokens in request payloads
4) For any requests which return data that may be sent back to the server, include a nonce (single use token) in your responses.
5) later requests should (must) include the nonce and the cookie
Again, my recommendation is to review the OWASP guidelines and proceed accordingly.
You may want to look into using a service provider for authentication - this is much smarter than brewing your own solution as there are literally a million details that all must be correct. Auth0.com is one of these.
I have a webservice. I am creating a test application to get response from this webservice. Added service reference to the web service application.
Logic in my test appplication is below.
for(int i=0;i<100;i++)
{
MyServiceSoapClient wsClient = new MyServiceSoapClient();
wsClient.Endpoint.Address = new EndpointAddress(serverAddress);
MyLoginResponse loginResp=wsClient.Login("X","X");
}
Just wanted to know whether I am making a persistent connection or a non persistent connection in this approach. Any help?
Test your webservice using curl. Pass curl the -v (verbose) flag. If you see Connection: close in the response header, your web service does not support persistent connections.