I used Jersey Client in the project like this:
clientConfig.connectorProvider(new ApacheConnectorProvider());
clientConfig.register(MultiPartFeature.class);
client = ClientBuilder.newClient(clientConfig);
it actually use httpClient to do the job. but now I encountered the CookieSpec issue in this question: Fixing HttpClient warning “Invalid expires attribute” using fluent API. I need to change the CookieSpec but I cannot find where to change the config.
Maybe you can try to use the below solution:
RequestConfig requestConfig = RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build();
clientConfig.property(ApacheClientProperties.REQUEST_CONFIG, requestConfig);
Related
I would like to consume a Soap Service provided by DHL. You can find the wsdl here: https://wsbexpress.dhl.com/sndpt/expressRateBook?WSDL
Therefore I created a new ClassLibrary in Visual Studio 2015 targeting .net framework 4.5.
Then I added a Web Reference to the created project by providing the wsdl address. I generated a proxy file with all types and ports in it but my first problem is, that the generated Service extends from System.Web.Services.Protocols.SoapHttpClientProtocol. As I read in recent posts it is not possible to get the wsse header to that proxy. Some posts advise to add wse but it seems wse is not supported by newer Visual Studio versions.
I tried to generate my proxy by svcutil. After that I added the generated .cs file to the project and copied the content of the generated config file to app.config. (of cause I removed the web reference)
Now the Service class extends System.ServiceModel.ClientBase. (I thought the generator in VS uses svctool internally. If microsoft want people to use wcf why does the generator generate non-wcf proxy files.
I also created a nunit testproject which should test my service, but If I use the version with the svcutil generated version I get an error. I try to translate it to english as the error is displayed in german:
Could not find a default endpoint element which points to the service contract. As I figured out this is because the proxy is in its own class library and therefor doesn't really have an app.config. But my test project is a class library too.
What would be the actual way to consume a web service which needs ws security Username/Password auth these days?
You can add the Web Reference in compatibility mode (I am guessing you are doing so). If you are not adding the reference in compatibility mode, do the following:
Right click on references Add Service Reference-> Advanced -> Add Web Reference (Below the compatibility section), type the URL of the WS and add the reference.
The WSE2.0 extensions are available as a Nuget Package at:
https://www.nuget.org/packages/Microsoft.Web.Services2/
Install the nuget package on the package manager console running the following nugget command:
Install-Package Microsoft.Web.Services2
After you installed the nuget package, you need to make sure your project is referencing the following DLL's:
System.Web
System.Web.Services
Microsoft.Web.Services2 (This will be added after you install the nuget package)
In order to use the WSE2.0 extensions, you need to actually modify the Proxy class that was created when you added the WebReference to inherit from "Microsoft.Web.Services2.WebServicesClientProtocol" instead of "System.Web.Services.Protocols.SoapHttpClientProtocol". Be aware that if you update the WebReference, the Proxy class will inherit againfrom SoapHttpClientProtocol.
Add the following using clauses to the code consuming the Proxy class:
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
After you make this changes, you code should look something like this:
var token = new UsernameToken("theUser", "thePassword", PasswordOption.SendHashed);
var serviceProxy = new ExpressRateBook.gblExpressRateBook();
SoapContext requestContext = serviceProxy.RequestSoapContext;
requestContext.Security.Timestamp.TtlInSeconds = 60;
requestContext.Security.Tokens.Add(token);
//The rest of the logic goes here...
I added the screenshot down below for your reference:
NOTE: I was unable to test the code since I am unfamiliar with the actual methods that you need to consume, the code displayed is just an example of what I saw in the proxy class, update it according to your needs. It should work fine if you follow the steps described before. Check the following link for more detailed instructions:
https://msdn.microsoft.com/en-us/library/ms819938.aspx
You can configure you Service Reference to add the Security Header as AW Rowse describes at http://cxdeveloper.com/article/implementing-ws-security-digest-password-nonce-net-40-wcf:
private void Configure()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; };
defaultBinding = new BasicHttpBinding
{
Security =
{
Mode = BasicHttpSecurityMode.Transport,
Transport =
{
ClientCredentialType = HttpClientCredentialType.Digest
}
}
};
defaultToken = new UsernameToken(UserName, Password, PasswordOption.SendHashed);
defaultSecurityHeader = MessageHeader.CreateHeader(
"Security",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
defaultToken.GetXml(new XmlDocument())
);
}
And create you client/proxy like this:
public consulta_informacao_respttClient CriaConsultaClinicaClient()
{
var client = new consulta_informacao_respttClient(defaultBinding, new EndpointAddress("https://resqa.homologacao.unimed.coop.br/chs-integration-external-services-ptu-clinical/proxy-services/execute-query/execute-query-proxy-service"));
client.ClientCredentials.UserName.UserName = UserName;
client.ClientCredentials.UserName.Password = Password;
var scope = new OperationContextScope(client.InnerChannel);
OperationContext.Current.OutgoingMessageHeaders.Add(defaultSecurityHeader);
return client;
}
The properties you will need to create in your class are:
private BasicHttpBinding defaultBinding;
private UsernameToken defaultToken;
private MessageHeader defaultSecurityHeader;
You won't need to configure anything in app/web.config.
I've implemented a simple SOAP webservice client to test the functionality but whether my client or in iex, and regardless of the target service I always get {:ok, :undefined, :undefined}
Here is my code:
wsdl_url = "http://www.webservicex.net/convertVolume.asmx?WSDL"
action = "ChangeVolumeUnit"
parameters = ["100", "dry", "centiliter"]
Detergentex.call(wsdl_url, action, parameters)
I'm using Versions:
Elixir: 1.2.0
Detergentex: 0.0.7
My mix.exs deps:
[{:erlsom, github: "willemdj/erlsom"},{:detergentex, "0.0.7"}]
Any suggestions on what I'm missing would be greatly appreciated.
1.) It's got a dependency on the detergent package.
Have you added the dependency for detergent? If not modify your mix.exs to this:
[{:erlsom, github: "willemdj/erlsom"},{:detergentex, "0.0.7"}, {:detergent, "~> 0.3.0"}]
2.) You also need to add detergentex to the list of applications as well:
def application do
[applications: [:logger, :detergentex]]
end
3.) The fact that it's returning {:ok, :undefined, :undefined} may simply indicate an issue with the endpoint or the message you're passing. Therefore I'd try it against an endpoint you're sure is good with a message you're sure will work. Perhaps the valid parameters to the endpoint they mention in their docs have changed since the docs were prepared.
By the way, I did see that you mentioned "regardless of the target service" but given it seems that you failed to add that detergent dependency and the fact that it looks like you forgot to add detergent to the application list, I'd still try some of those other SOAP endpoints again since you've changed things.
I have a REST service implemented in Restlet + JAXRS extension.
At a certain point, I had to add the CORS headers to responses.
I have a lot of REST calls, and adding by hand the headers as this is working:
return Response.status(200).header("Access-Control-Allow-Origin", "*").
header("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, Content-Type").
header("Access-Control-Expose-Headers", "Location, Content-Disposition").
header("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, HEAD, OPTIONS").
entity(fsJSON).build();
but I'd like to use filters in order to add those headers to all the responses, without adding those manually. I found a lot of examples of using filters in JAX-RS, like those:
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
http://javatech-blog.blogspot.it/2015/04/jax-rs-filters-example.html
http://blog.dejavu.sk/2014/02/04/filtering-jax-rs-entities-with-standard-security-annotations/
But I can't understand how to integrate them with Restlet + JAX-RS environment. For example, I can't see the ContainerResponseFilter class anywhere.
Anyone can help me?
When creating a JaxRS application within Restlet, you create a JaxRsApplication (see this link: http://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs). This class extends the standard application of Restlet. The latter provides the way to configure services on it using the getServices method.
So in your case, you don't need to use filters...
See this answer regarding the configuration of the CorsService of Restlet: How to use CORS in Restlet 2.3.1?.
Here a way to configure CORS within a Restlet JaxRS application:
Component comp = new Component();
Server server = comp.getServers().add(Protocol.HTTP, 8182);
JaxRsApplication application = new JaxRsApplication(comp.getContext());
application.add(new ExampleApplication());
CorsService corsService = new CorsService();
corsService.setAllowedOrigins(new HashSet(Arrays.asList("*")));
corsService.setAllowedCredentials(true);
application.getServices().add(corsService);
component.getDefaultHost().attachDefault(application);
Otherwise JAX-RS filters aren't supported by the corresponding extensions of Restlet. To add a filter, you need to add it as a Restlet filter in front of the application, as described below:
JaxRsApplication application = new JaxRsApplication(comp.getContext());
application.add(new ExampleApplication());
MyRestletFilter filter = new MyRestletFilter();
filter.setNext(application);
component.getDefaultHost().attachDefault(filter);
Hope it helps you,
Thierry
I parse website 'http://ok.ru'. To get data from the post request I need to send a specific token that is generated by Javascript on the website and this token is contained in headers.
So I thought maybe one solution would be to open the website, let it generate token, grab headers and that's it.
One tool that can implement Java scripts is Selenium, however, to get headers I need to use brosermob-proxy (or equivalent). That is where I'm stuck.
There's no headers in response and I can't figure it out. Maybe someone who worked with browsermob can see what's wrong? I would also be glad to hear another solutions to my task. The code itself is below:
from browsermobproxy import Server
from selenium import webdriver
from ast import literal_eval
import json, os
os.chdir('C:/browsermob-proxy-2.1.0-beta-2/bin')
server = Server()
server.start()
proxy = server.create_proxy()
profile = webdriver.FirefoxProfile()
profile.set_proxy(proxy.selenium_proxy())
driver = webdriver.Firefox(firefox_profile=profile)
proxy.new_har('test')
driver.get('http://ok.ru')
driver.find_element_by_xpath('//input[#name="st.email"]').send_keys('****#****.com')
driver.find_element_by_xpath('//input[#name="st.password"]').send_keys('****')
driver.find_element_by_xpath(u'//input[contains(#value,"Log in")]').click()
result = literal_eval(json.dumps(proxy.har, ensure_ascii=False))
driver.close()
for entry in result['log']['entries']:
if len(entry['response']['headers']) > 0:
print entry['response']['headers']
The answer turned to be easy: just to add options to new_har:
proxy.new_har('test', options={'captureHeaders': True})
However, there is no token in headers, which is a new puzzle to me...
There are some similar questions for earlier versions of Jetty (pre 9) but none that address this specific problem :
Server server = new Server();
System.setProperty("com.sun.net.httpserver.HttpServerProvider",
JettyHttpServerProvider.class.getName());
JettyHttpServer jettyServer = new JettyHttpServer(server, true);
Endpoint endpoint = Endpoint.create(new SOAPService()); // this class to handle all ws requests
endpoint.publish(jettyServer.createContext("/service")); // access by path
server.start()
Simplified code example above to show the only way that I have found to bridge between Jetty and incoming soap requests to my jax-ws service. All settings are in code with no web.xml, this is part of a larger solution that has multiple contexts and connections for different purposes (servlets etc..)
I have tried to add a handler class to the jettyServer.createContext("/service",new handler()) to see if I can perform a header extraction to simulate basic auth but it never gets executed.
My problem is that i cannot find a way to specify, by code against the Jetty server, to use basic authentication. Using the setSecurityHandler method of a ServletContextHandler is easy and works great for other contexts, i just can't figure out how to use this concept for the jax-ws service.
Any help would be much appreciated.
p.s. SSL is already implemented, I just need to add http basic auth.
For anyone else that may of come across the same problem here is the answer that i stumbled on eventually.
final HttpContext httpContext = jettyServer.createContext("/service");
com.sun.net.httpserver.BasicAuthenticator a = new com.sun.net.httpserver.BasicAuthenticator("") {
public boolean checkCredentials (String username, String pw)
{
return username.equals("username") && pw.equals("password");
}
};
httpContext.setAuthenticator(a);
endpoint.publish(httpContext);//access by path
You can expand the checkCredentials for something a bit more sophisticated of course, but this shows the basic working method.