Camel CXF SOAP API Consumer with https and Security Header - soap
I'm currently facing the issue, that I can not consume a SOAP webservice via camel-cxf. The exception is the following:
org.apache.cxf.ws.policy.PolicyException: These policy alternatives can not be satisfied:
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}TransportBinding: Received Timestamp does not match the requirements
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}IncludeTimestamp
at org.apache.cxf.ws.policy.AssertionInfoMap.checkEffectivePolicy(AssertionInfoMap.java:179) ~[109:org.apache.cxf.cxf-rt-ws-policy:3.2.6]
at org.apache.cxf.ws.policy.PolicyVerificationInInterceptor.handle(PolicyVerificationInInterceptor.java:102) ~[109:org.apache.cxf.cxf-rt-ws-policy:3.2.6]
at org.apache.cxf.ws.policy.AbstractPolicyInterceptor.handleMessage(AbstractPolicyInterceptor.java:44) ~[109:org.apache.cxf.cxf-rt-ws-policy:3.2.6]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) ~[78:org.apache.cxf.cxf-core:3.2.6]
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:813) [78:org.apache.cxf.cxf-core:3.2.6]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1695) [102:org.apache.cxf.cxf-rt-transports-http:3.2.6]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream$1.run(HTTPConduit.java:1194) [102:org.apache.cxf.cxf-rt-transports-http:3.2.6]
at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$3.run(AutomaticWorkQueueImpl.java:421) [78:org.apache.cxf.cxf-core:3.2.6]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$AWQThreadFactory$1.run(AutomaticWorkQueueImpl.java:346) [78:org.apache.cxf.cxf-core:3.2.6]
at java.lang.Thread.run(Thread.java:748) [?:?]
and the SOAP answer the following:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode><faultstring xml:lang="de-DE">An error occurred when verifying security for the message.</faultstring></s:Fault></s:Body></s:Envelope>
I used the maven cxf-codegen-plugin to generate the Java-classes via the wsdl2java goal.
The security part of the wsdl looks like this:
<wsp:Policy wsu:Id="BasicHttpBinding_IUserManagementService_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy/>
</sp:Wss10>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
and I want to use the UsernameToken authentication.
Maven dependencies:
camel version: 2.20.3
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-blueprint</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-soap-starter</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-ws-security</artifactId>
<version>3.2.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-ws-policy</artifactId>
<version>3.2.6</version>
<scope>provided</scope>
</dependency>
I tried to connect to the api via SoapUI and everything worked well. Either with the authentication-part of SoapUI or with specifying the security part in the SoapHeader, both worked.
My camel route-builder looks like this:
SoapJaxbDataFormat soap = new SoapJaxbDataFormat("org.tempuri", new ServiceInterfaceStrategy(IUserManagementService.class, true));
from("direct:userdata.soap.requests")
// .marshal(soap) // not sure, if I need to marshal here
.to("cxf://{{SOAP_URL}}" +
"?serviceClass=org.tempuri.IUserManagementService" +
"&serviceName={http://tempuri.org/}UserManagementService" +
"&endpointName={http://tempuri.org/}BasicHttpBinding_IUserManagementService" +
"&wsdlURL={{WSDL_URL}}" +
"&dataFormat=MESSAGE" +
"&username={{SOAP_USERNAME}}" +
"&password={{SOAP_PASSWORD}}" +
"&allowStreaming=false");
and I'm sending to the queue like this:
#EndpointInject(uri = "direct:userdata.soap.requests")
Endpoint endpoint;
#Produce(uri = "direct:userdata.soap.requests")
ProducerTemplate channel;
....
private Object sendRequest(Object request, String operationName) throws Exception{
Exchange inExchange = endpoint.createExchange(ExchangePattern.InOnly);
inExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, operationName);
inExchange.getIn().setHeader(CxfConstants.OPERATION_NAMESPACE, "http://tempuri.org/");
inExchange.getIn().setBody(request);
Map<String, Object> context = new HashMap<>();
context.put("ws-security.username", soapUsername);
context.put("ws-security.password", soapPassword);
inExchange.getIn().setHeader(Client.REQUEST_CONTEXT, context);
Exchange outExchange = channel.send(inExchange);
log.error(outExchange.getOut().getBody(String.class));
Object result = outExchange.getIn().getBody(Object.class);
if(result.getClass().equals(FaultException.class)){
throw (FaultException) result;
}
return result;
}
where endpoint is type org.apache.camel.Endpoint and channel is type org.apache.camel.ProducerTemplate
The request-Object is of type from the autogenerated classes by the plugin.
I also tried, writing my own WSS4JOutInterceptor to handle the security part, but this also did not work.
Please let me know, if I need to provide more information.
Many thanks in advance
It turned out, there was an issue, interpreting the SOAP answer.
So actually the route works like this. Just set the headers ws-security.username and ws-security.password and the cxf will take care of creating the correct header.
I've also changed the dataformat to PAYLOAD and marshalling is not needed at this point.
Thanks anyway for reading
Related
The background display of the startup project is as follows
Spring integrates jwt to realize login. pom.xml configuration <!--security--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!--JWT--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> <dependency> <groupId>org.jetbrains</groupId> <artifactId>annotations</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> </dependencies> application.yml configuration logging: level: com.xxxx.server.mapper: debug jwt: tokenHeader: Authorization secret: yeb-secret expiration: 604800 tokenHead: Bearer Running the project background prompts the following information. Description: Failed to bind properties under 'logging.level.jwt.tokenheader' to org.springframework.boot.logging.LogLevel: Property: logging.level.jwt.tokenheader Value: "Authorization" Origin: class path resource [config/application.yml] - 52:20 Reason: failed to convert java.lang.String to org.springframework.boot.logging.LogLevel (caused by java.lang.IllegalArgumentException: No enum constant org.springframework.boot.logging.LogLevel.Authorization) Why it can't works? thanks!!
How to create Azure Managed Disk Snapshot with Encryption and Network Access Policy?
I am trying to use the SDK to create a snapshot for the managed disk using the below azureSdkClients .getComputeManager() .snapshots() .define(snapshotName) .withRegion(disk.regionId) .withExistingResourceGroup(context.resourceGroupName); .withWindowsFromDisk(context.azureDisk) .withIncremental(incr) .create() But this doesn't have the options for setting encryption and network acess policy? Is it supported by the SDK API ? or should I use a different API ? I see SnapshotInner as one implementation of Snapshot. I am not sure if I can use the inner class as it doesn't allow me to set the name of the snapshot
Regarding the issue, please refer to the following steps SDK <dependency> <groupId>com.azure.resourcemanager</groupId> <artifactId>azure-resourcemanager-compute</artifactId> <version>2.2.0</version> </dependency> <dependency> <groupId>com.azure.resourcemanager</groupId> <artifactId>azure-resourcemanager-keyvault</artifactId> <version>2.2.0</version> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.2.3</version> </dependency> Code String clientId=""; String clientSecret=""; String tenant=""; String subId=""; AzureProfile profile = new AzureProfile(tenant,subId, AzureEnvironment.AZURE); TokenCredential credential = new ClientSecretCredentialBuilder() .clientId(clientId) .clientSecret(clientSecret) .authorityHost(profile.getEnvironment().getActiveDirectoryEndpoint()) .tenantId(tenant) .build(); ComputeManagementClientImpl computeClient = new ComputeManagementClientBuilder() .pipeline(HttpPipelineProvider.buildHttpPipeline(credential,profile)) .endpoint(profile.getEnvironment().getResourceManagerEndpoint()) .subscriptionId(profile.getSubscriptionId()) .buildClient(); SnapshotInner sp = new SnapshotInner() .withCreationData(new CreationData().withSourceResourceId("") .withCreateOption(DiskCreateOption.COPY)) .withSku(new SnapshotSku().withName(SnapshotStorageAccountTypes.PREMIUM_LRS)) .withEncryption(new Encryption().withType(EncryptionType.ENCRYPTION_AT_REST_WITH_PLATFORM_KEY)) .withNetworkAccessPolicy(NetworkAccessPolicy.ALLOW_ALL) .withLocation("eastasia"); computeClient.getSnapshots().createOrUpdate("testdata","testdfg",sp); For more details, please refer to here.
Restlet client resource "not modified" condition
I've got a Restlet based application, and I'm trying to use Restlet client resources to test certain parts of it. Since upgrading from Restlet 2.2.3 to 2.3.4, my ETag verification tests have started failing. Here's how I was adding the header in the old version: Series<Header> headers = (Series<Header>) currentClientResource.getRequest().getAttributes().get("org.restlet.http.headers"); if (headers == null) { headers = new Series<Header>(Header.class); } headers.add("If-None-Match", "\"" + eTag + "\""); currentClientResource.getRequestAttributes().put("org.restlet.http.headers", headers); Then when calling represent() again on the wrapped clientResource I was getting a 304 Not Modified response (which is what I want). In 2.3.4 this started returning a 200 OK instead, and I noticed a log message about not setting the If-None-Match header directly. Instead I'm now trying this: currentClientResource.getRequest().getConditions().getNoneMatch().add(new Tag(eTag)); However this is still giving me a 200 OK. If I do the request manually through a REST client I can get a 304 Not Modified, so the server is still doing the right behavior. What do I need to do in the tests to see what I want to see?
I made a try and it works for me with version 2.3.4 of Restlet. Here is what I did: The Maven dependencies for my test <project> <modelVersion>4.0.0</modelVersion> (...) <properties> <java-version>1.7</java-version> <restlet-version>2.3.4</restlet-version> </properties> <dependencies> <dependency> <groupId>org.restlet.jse</groupId> <artifactId>org.restlet</artifactId> <version>${restlet-version}</version> </dependency> <dependency> <groupId>org.restlet.jse</groupId> <artifactId>org.restlet.ext.jetty</artifactId> <version>${restlet-version}</version> </dependency> <dependency> <groupId>org.restlet.jse</groupId> <artifactId>org.restlet.ext.jackson</artifactId> <version>${restlet-version}</version> </dependency> <dependency> <groupId>org.restlet.jse</groupId> <artifactId>org.restlet.ext.crypto</artifactId> <version>${restlet-version}</version> </dependency> </dependencies> <repositories> <repository> <id>maven-restlet</id> <name>Public online Restlet repository</name> <url>http://maven.restlet.com</url> </repository> </repositories> </project> A server resource that sets the etag on the returned representation: public class ETagServerResource extends ServerResource { #Get public Representation test() { String test = "test"; String md5 = DigestUtils.toMd5(test); StringRepresentation repr = new StringRepresentation(test); repr.setTag(new Tag(md5)); return repr; } } The client that makes two calls: a first one without the etag and a second one with the etag that should return a 304 status code. // First call ClientResource cr = new ClientResource("http://localhost:8182/test"); Representation repr = cr.get(); Tag tag = repr.getTag(); System.out.println(">> cr = "+cr); // Status code: 200 // Second call cr.getRequest().getConditions().getNoneMatch().add(tag); cr.get(); System.out.println(">> cr = "+cr); // Status code: 304 I don't know what you use within the server resource. Feel free to tell me. Hope it helps you, Thierry
Need help in REST ASSURED
I am starting with REST Assured, getting error while executing below code : Code 1- RestAssured.expect().statusCode(200). body( "name", equalTo("Russia") ). when(). get("http://restcountries.eu/rest/v1/callingcode/7"); Exception- Exception in thread "main" java.lang.Error: Unresolved compilation problem: The method equalTo(String) is undefined for the type Code 2 - RestAssured.expect().statusCode(200). body( "name", Matchers.equalTo("Russia") ). when(). get("http://restcountries.eu/rest/v1/callingcode/7"); Exception- Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: com.jayway.restassured.internal.ContentParser.parse() is applicable for argument types: (com.jayway.restassured.internal.RestAssuredResponseImpl, com.jayway.restassured.internal.ResponseParserRegistrar, com.jayway.restassured.config.RestAssuredConfig, java.lang.Boolean) values: [com.jayway.restassured.internal.RestAssuredResponseImpl#753455ab, ...] Possible solutions: wait(), any(), grep() Below are the only 2 methods in my class, I am having issue with first one, second one is running fine. Please let me know what I am missing in first method. Method -1 public static void testCountriesCallingCode() { RestAssured.expect().statusCode(200). body( "name", equalTo("Russia") ). when(). get("http://restcountries.eu/rest/v1/callingcode/7"); System.out.println(RestAssured.get("http://restcountries.eu/rest/v1/callingcode/7").asString()); } Method-2 public static void testCountriesCallingCodeUsingJSONPATH(){ Response res = RestAssured.get("http://restcountries.eu/rest/v1/callingcode/7"); System.out.println(res.getStatusCode()); String json = res.asString(); JsonPath jp = new JsonPath(json); System.out.println(jp.get("name")); }
Thanks Hti, your answer worked. Without the other dependencies, Rest Assured kind of works. I have no idea why Rest Assured website does not note this. Following in pom.xml worked <properties> <rest-assured.version>3.0.2</rest-assured.version> <resteasy.version>3.0.17.Final</resteasy.version> </properties> ... <!-- Jackson is for allowing you to convert pojo (plain old Java object) into JSON --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson-provider</artifactId> <version>${resteasy.version}</version> </dependency> <dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <version>${rest-assured.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>io.rest-assured</groupId> <artifactId>json-path</artifactId> <version>${rest-assured.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>io.rest-assured</groupId> <artifactId>xml-path</artifactId> <version>${rest-assured.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-xml</artifactId> <version>2.4.11</version> <scope>test</scope> </dependency>
Change the body of your first example to: body( "[0].name", equalTo("Russia") ) That is because the JSON response from the server is not an object, but an array, and you have to query for the first object ([0]), then the name (.name).
For the Code-1, for equalTo() method you have to import org.hamcrest.Matchers.*; For the exception in code 2, it is very hard to mention without looking at the RESPONSE but try to follow below link if you have nested generic parameters in your response. How to validate nested response using REST Assured? Please let me know if you have any issue or question. Thanks!
Even though this question is old, I just stumpled upon the second problem: Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: com.jayway.restassured.internal.ContentParser.parse() is applicable for argument types: (com.jayway.restassured.internal.RestAssuredResponseImpl, com.jayway.restassured.internal.ResponseParserRegistrar, com.jayway.restassured.config.RestAssuredConfig, java.lang.Boolean) values: [com.jayway.restassured.internal.RestAssuredResponseImpl#753455ab, ...] Possible solutions: wait(), any(), grep() This is due to missing dependencies. In my case I needed to add the dependencies for xml-path and groovy-xml, even though I'm just working with JSON data. So the best thing to do is resolving the dependencies transitively.
equalTo comes from Hamcrest which is a JUnit dependency contained within the JUnit jar. You probably just need to import the static method for it from Hamcrest. import static org.hamcrest.core.IsEqual.*;
Add a static package for equal to: import static org.hamcrest.Matchers.*;
JAX-RS Jersey Error java.lang.NoSuchMethodError
I wanted to implement a file-upload function for my jersey based rest server. when i set my pom.xml (using maven) to: <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-multipart</artifactId> <version>2.4.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-jdk-http</artifactId> <version>2.0</version> </dependency> i get following error: JAX-RS Jersey Error java.lang.NoSuchMethodError: org.glassfish.jersey.internal.util.ReflectionHelper.getContextClassLoaderPA()Ljava/security/PrivilegedAction; without the "jersey-media-multipart"-dependency the rest server is working but i cant use the file-upload functions. Following the important part of source code: ResourceConfig resourceConfig = new ResourceConfig(RestWebServer.class); //resourceConfig.register(MultiPartFeature.class); URI endPoint = new URI(pathServer); server = JdkHttpServerFactory.createHttpServer( endPoint, resourceConfig ); RestWebserver.java: #Path("/fileupload") #POST #Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFile( #FormParam("file") InputStream uploadedInputStream, #FormParam("file") FormDataContentDisposition fileDetail) { String uploadedFileLocation = "c://" + fileDetail.getFileName(); // save it saveToFile(uploadedInputStream, uploadedFileLocation); String output = "File uploaded via Jersey based RESTFul Webservice to: " + uploadedFileLocation; return Response.status(200).entity(output).build(); }
Not a Jersey user so I am just guessing, but you probably have a jar mismatch. Try replacing your second entry with this: <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-jdk-http</artifactId> <version>2.4.1</version> </dependency>
Basing my guess on the chapter 8, have you registered your client/server code?