How to read the user or identifier supplied in ws-security - java

I am using latest Apache CXF to create a webservice. I have configured ws-security using org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor. In my passwordCallbackClass I can access the user or identifier by calling getIdentifier() method of org.apache.ws.security.WSPasswordCallback class.
I am also using spring for the whole setup.
I would like to know how to access the identifier any where else in the code? I could think of using ThreadLocal in my passwordCallbackClass? Another way is define to an identifier property in all my service method parameters but that would mean client need to pass the identifier twice, one in the security block and again in the service call?
Edit
My service class looks like this and I need to read the Identifier in sayHi method.
#WebService(endpointInterface = "com.webservice.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
return "Hello " + text;
}
}
My Password callback method is this where I can get the Identifier.
public void handle(Callback[] callbacks) throws IOException,UnsupportedCallbackExceptio {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.getIdentifier();
}

I used ThreadLocal in my Password callback method to store the Identifier. I then access the ThreadLocal anywhere in the code to know the identifier.

Define "any where else in the code"? Are you talking about in other interceptors? In your server implementation? Are you using JAXWS or the simple frontend? Etc...
If using jaxws and you want it in your server impl, the JAXWS WebServiceContext has a getUserPrincipal() method that would just be a principal that WSS4J creates after you validate the user.
Pretty much anywhere else (or even in the server impl using the context), you can do something like:
message.get(SecurityContext.class).getUserPrincipal();
to achieve the same result.

Related

How to create a java client for a Spring service?

I have a service definition using Spring annotations. Example (source):
#RequestMapping(value = "/ex/foos/{id}", method = GET)
#ResponseBody
public String getFoosBySimplePathWithPathVariable(
#PathVariable("id") long id) {
return "Get a specific Foo with id=" + id;
}
The question is whether spring (or another library) can auto-create a remote implementation (client) of the same API without the need to manually type paths, method type, param names, etc. (like needed when using RestTemplate)?
Example of an such a client usage:
FooClient fooClient = new FooClient("http://localhost:8080");
String foo = fooClient.getFoosBySimplePathWithPathVariable(3l);
How can I get to such a client "generated" implementation"?
You are probably looking for Feign Client. It does everything you need: calling one service via HTTP is similar to calling method of Java interface. But to make it work you need Spring Cloud, standard Spring framework doesn't have this feature yet.
You can generate it using Swagger Editor. You shoud just define the path of the resources and then it'll generate for you the client for almost any language of your choice

Find out which endpoint sent a REST call

I'm trying to create a visualisation of REST calls among several internal and external services/servers. I'd like to know which endpoint called which other endpoint. I figured that the only way to do this is to do this on the caller side, because the receiver does not have any information about the caller endpoint.
Here's my thinking:
I create an object like RestTemplate and call the method.
I create an Interceptor or something like that, which will extract the information from the RestTemplate.
My problem is that I'm not sure how to find out which REST endpoint called the RestTemplate method. The RestTemplate (or other similar object) call could be called in nested methods, so for example the endpoint could invoke a private method, which then calls the external service itself.
Is there any way how to get this information? Or am I maybe just thinking too hard and there is an easier way to do this?
Example:
#GetMapping("/hello")
public String hello() {
methodThatCallsOtherEndpoint("something.com/weather"); // this method inside itself calls an endpoint
logRestCall("localhost:8000/hello", "something.com/weather"); // how do I do this automatically without having to type it myself?
return "hello";
}
Thanks for any help.
If these services/servers have a static IP you can possibly, tag them by their IP address?
You can use Spring Sleuth to trace the relationship between different REST calls.

Is posible accept all kind of resources in Restful Jersey web service?

Is there any way to accept and handle any resource, i.e.
I want to handle myappname/xxx where xxx could be anything, and how could I handle?
Note: I already know is posible create any class and then bind a resource to a class, but I don't want it. I want a one universal class that handles every resource.
I don't know Jersey well, but as it implements JAX-RS I expexted that would work (not tested):
#Path("/myappname")
public class CatchItAll {
#GET
#Path("/{anyThing:.*}")
public String catch(#PathParam("anyThing") String anyThing) {
}
}
It uses the regular expression feature.

Java - using SOAP with generated from WSDL classes

I have a WSDL schema link. With NetBeans I generated classes from this schema. But I can't understand, how to use it to send request to server? There is a XXXImplService extends Service class generated by NetBeans, should I use it? How?
As I think, I need just to create objects (which match WSDL methods and classes), set necessary properties and somehow transform this objects into a text of request, then send it with and get text response, which I can transform into classes. Is this true?
of course you have to use the WSDL, follow below steps for a complete client app for a Java web service (JAX-WS):
assuming you have a Web Service like this:
#WebService
public class Hello {
private String message = new String("Hello, ");
public void Hello() {}
#WebMethod
public String sayHello(String name) {
return message + name + ".";
}
}
Uses the javax.xml.ws.WebServiceRef annotation to declare a
reference to a web service. #WebServiceRef uses the wsdlLocation
element to specify the URI of the deployed service’s WSDL file:
#WebServiceRef(wsdlLocation="http://localhost:8080/helloservice/hello?wsdl")
static HelloService service;
Retrieves a proxy to the service, also known as a port, by invoking
getHelloPort on the service.
Hello port = service.getHelloPort();
The port implements the SEI defined by the service.
Invokes the port’s sayHello method, passing to the service a name.
String response = port.sayHello(name);
EDIT: (request in comments) if the web service request for basic authentication and want to pass a username and password you can pass them like this (there are other ways also):
import java.net.Authenticator;
import java.net.PasswordAuthentication;
Authenticator authenticator = new Authenticator()
{
#Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication("usr", "pass".toCharArray());
}
};
Authenticator.setDefault(authenticator );
however if you want authentication in application level not on basic
HTTP this link can be useful.
You have to implement your code in this generated service impl and web method now. So when you will be calling the service end point and a specific method, through a web service client ( SOAP UI etc), these generated classes will take the call and route through service impl, to your implementation.
This tutorial will help you to do it step by step. Since you have already created stub classes, skip the first part. Focus on "Web service invocation" section.
http://www.ibm.com/developerworks/webservices/library/ws-apacheaxis/index.html?ca=dat

Jax-WS - When implementing a Web Service, can you call another web service like calling any pojo?

Suppose I have the following 2 web service code, I think I can do the following
#WebService
public class WS1 {
#WebMethod
public String hello() {
WS2 ws2 = new WS2();
ws2.method2();
}
#WebService
public class WS2 {
#WebMethod
public String method2() {
//implementation of method2.
}
I've tested and it worked. Now the question is: is there any side effect or unforeseen consequences that I am not aware of if I do this? Can I call the 2nd web service object like any normal pojo from server side?
that will work in terms of basic code execution. however, the ws2 instance you instantiate will not have any "container managed" stuff done to it. e.g., dependency injection won't work, any transaction/security support for that service will be ignored, etc. in other words, it's probably not what you want to do in the general case.

Categories

Resources