Sending Secure Request Using Spring WebserviceTemplate - java

I have created a web service client using spring ws template. This is working as expected for http protocol. Now I want to make it work with https. I have the relevant client key store(the jks file) and now I want to configure the message sender to send secure request.
Could you please help me on how to proceed on this?
Here is my spring bean configuration:
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="tokenrMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="com.token.dto.v1" />
</bean>
<bean id="tokenServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="tokenrMarshaller"></property>
<property name="unmarshaller" ref="tokenrMarshaller"></property>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender" />
</property>
<property name="defaultUri" value="${token.url}" />
</bean>
If I change the url from http to https w/o any configuration, the application throws "org.springframework.ws.client.WebServiceTransportException".

See javadoc for http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html#setHttpClient%28org.apache.http.client.HttpClient%29
Set httpClient property of messageSender bean.
See my other post on how to configure httpClient bean to work around self-signed certificate issues.
sending https post request with post data using spring web
No need to import keys into keystore.

Related

How to configure Camel HTTP4 Component to use NTLM Authentication

In Spring DSL, How can Camel's HTTP4 component be configured to use NTLM authentication?
I am able to configure Camel's HTTP component to use NTLM authentication, successfully, using this Spring DSL configuration:
<!-- Works: HTTP (3) Configuration -->
<bean id="httpConfig" class="org.apache.camel.component.http.HttpConfiguration">
<property name="authMethod" value="NTLM"/>
<property name="authHost" value="my-active-directory-host"/>
<property name="authDomain" value="my-ad-domain"/>
<property name="authUsername" value="my-username"/>
<property name="authPassword" value="my-password"/>
</bean>
<!-- Works: HTTP (3) Component-->
<bean id="httpmw" class="org.apache.camel.component.http.HttpComponent">
<property name="camelContext" ref="camel"/>
<property name="httpConfiguration" ref="httpConfig"/>
</bean>
But, my best attempt to configure the HTTP4 component fails because I do not know how to set the httpClientConfiguration of the HttpComponent. Or perhaps, there is another way to wire the HTTP4 component?
<!-- Works: HTTP4 Configuration -->
<bean id="httpClientConfig" class="org.apache.camel.component.http.NTLMAuthenticationHttpClientConfigurer">
<constructor-arg name="proxy" value="false"/>
<constructor-arg name="user" value="my-username"/>
<constructor-arg name="pwd" value="my-password"/>
<constructor-arg name="domain" value="my-ad-domain"/>
<constructor-arg name="host" value="my-active-directory-host"/>
</bean>
<!-- Does not work: HTTP4 Component, exception
Caused by: org.springframework.beans.NotWritablePropertyException:
Invalid property 'httpClientConfiguration' of bean class [org.apache.camel.component.http4.HttpComponent]:
Bean property 'httpClientConfiguration' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
-->
<bean id="http4mw" class="org.apache.camel.component.http4.HttpComponent">
<property name="camelContext" ref="camel"/>
<property name="httpClientConfiguration" ref="httpClientConfig"/>
</bean>

Camel Property-Placeholder: Not able to configure `camel:sslContextParameters` with nested properties

I am using Camel-HTTP4 2.10.4 component for calling remote REST services from my application. This communication requires SSL configuration. I successfully tested my configuration with hard coded values for resource and password.
Now I need to configure the same using camel's Property-Placeholder. I am using nested properties in spring configuration. ex:
${${env:${default.fallback.env}}.path.to.keystore}
I followed Using PropertyPlaceholder and defined
<bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="locations">
<list>
<ref bean="confgPath1" />
<ref bean="configPath2" />
</list>
</property>
</bean>
and sslContextParameters as follows
<camel:sslContextParameters id="sslContextParameters">
<camel:trustManagers>
<camel:keyStore resource="{{{{default.fallback.env}}.keystore.file}}"
password="{{{{default.fallback.env}}.keystore.password}}" />
</camel:trustManagers>
<camel:keyManagers keyPassword="{{{{default.fallback.env}}.keystore.password}}">
<camel:keyStore resource="{{{{default.fallback.env}}.keystore.file}}"
password="{{{{default.fallback.env}}.keystore.password}}" />
</camel:keyManagers>
<camel:clientParameters>
<camel:cipherSuitesFilter>
<camel:include>.*</camel:include>
</camel:cipherSuitesFilter>
</camel:clientParameters>
</camel:sslContextParameters>
My application loads spring context successfully at start up. But after hitting the endpoint I am getting Error:
Failed to resolve endpoint <<My remote service URL>> due to: Error parsing property value: {{{{default.fallback.env}}.keystore.password}}.
I am able to use Camel's property placeholder for simple properties. For ex
{{default.fallback.env}}
But, when I try to use nested properties it is giving me above specified Error. Help me find out the proper way to solve this.
Current camel property component doesn't support the nested properties, so I just fill a JIRA for it.
As Camel property doesn't support the nested properties in the first place, you can define just define the property file like this, and set the environment from the system property and use {{someproperty}} to reference the properties.
someproperty={{{{environment}}.someproperty}}
# LOCAL SERVER
junit.someproperty=junit
# LOCAL SERVER
local.someproperty=local
# TEST
test.someproperty=test
# PROD
prod.someproperty=prod
I just used the Spring way to create Camel SSL configuration:
<bean id="sslContextParameters" class="org.apache.camel.util.jsse.SSLContextParameters">
<property name="keyManagers">
<bean class="org.apache.camel.util.jsse.KeyManagersParameters">
<property name="keyPassword" value="${dsi.key.password}" />
<property name="keyStore">
<bean class="org.apache.camel.util.jsse.KeyStoreParameters">
<property name="resource" value="${dsi.keystore.file}" />
<property name="type" value="JKS" />
<property name="password" value="${dsi.keystore.password}" />
<property name="camelContext" ref="camelContext" />
</bean>
</property>
<property name="camelContext" ref="camelContext" />
</bean>
</property>
<property name="camelContext" ref="camelContext" />
</bean>
I believe with Spring's property resolver you can achieve more and you do not need to use the custom bridge resolver.

How to add a value from a cookie to the HTTP header in Spring WebServiceTemplate?

I am using Spring WebServiceTemplate in my client side code to send request to an existing 3rd party web service.
<bean id="vehicleQuotationWebServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="marshaller" ref="vehicleQuotationMarshaller" />
<property name="unmarshaller" ref="vehicleQuotationMarshaller" />
<property name="faultMessageResolver" ref="vehicleServiceClientFaultMessageResolver" />
<property name="defaultUri" value="http://localhost:8080/quote/endpoints"/>
</bean>
Everything was working fine until they added security check from the server side. Right now, in order to pass the server side security authenication, I need to pass some values from a cookie to the server. This I can do easily in SoapUI by modifying the http header (adding the cookie's value there), but my question is how can I do it in Java code with the Spring's WebServiceTemplate?
You can extend the WebServiceTemplate or in a more easy way use a custom sender who extends Spring's
org.springframework.ws.transport.http.CommonsHttpMessageSender
and set in your bean definition
<bean id="vehicleQuotationWebServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="marshaller" ref="vehicleQuotationMarshaller" />
<property name="unmarshaller" ref="vehicleQuotationMarshaller" />
<property name="faultMessageResolver" ref="vehicleServiceClientFaultMessageResolver" />
<property name="defaultUri" value="http://localhost:8080/quote/endpoints"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.MyHttpComponentsMessageSender"/>
</property>
</bean>
take a look at Spring forums
JSESSIONID and setting cookie for WebServiceTemplate

sending https post request with post data using spring web

I'm trying to understand how to send https post request with post data using spring web or and other spring tools.
so far I've been using httpclient but i'm trying to convert to spring :)
the https post request should ignore self signed certificate.
please provide an example on how it can be done.
thank you
I use Spring Integration to send http POST and GET
http://static.springsource.org/spring-integration/reference/html/http.html
The request-factory bean need to be configured to allow self-signed certificates.
I use the following wiring to declare apacheHttpsRequestFactory to be used by http Spring Integration endpoints.
The httpClient bean can be injected to other Spring Beans and used to send http requests:
#Autowired
private HttpClient httpClient;
Here is the fragment of spring-intefration-context.xml:
<!-- HTTPS connection to trust self signed certificates -->
<bean id="sslSocketFactory" class="org.apache.http.conn.ssl.SSLSocketFactory">
<constructor-arg name="trustStrategy">
<bean class="org.apache.http.conn.ssl.TrustSelfSignedStrategy" />
</constructor-arg>
<constructor-arg name="hostnameVerifier">
<bean class="org.apache.http.conn.ssl.AllowAllHostnameVerifier" />
</constructor-arg>
</bean>
<bean id="httpsSchemaRegistry" class="org.apache.http.conn.scheme.SchemeRegistry">
<property name="items">
<map>
<entry key="https">
<bean class="org.apache.http.conn.scheme.Scheme">
<constructor-arg value="https" />
<constructor-arg value="443" />
<constructor-arg ref="sslSocketFactory" />
</bean>
</entry>
</map>
</property>
</bean>
<bean id="httpClient" class="org.apache.http.impl.client.DefaultHttpClient">
<constructor-arg>
<bean class="org.apache.http.impl.conn.PoolingClientConnectionManager">
<constructor-arg ref="httpsSchemaRegistry" />
</bean>
</constructor-arg>
</bean>
<bean id="apacheHttpsRequestFactory"
class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient" />

Redirect to https for few services using spring

I have an application which uses spring (also spring security) where few services were kept outside the secured resource set by specifying like below in the applicationContext.xml:
<http pattern="/services/rest/nohisb/Msgs" security="none"/>
Now these services needs to be accessed only via https. Container is configured to have https. Requirement is when user access the above service on http, he should be redirected to https (port number too changes, as it in not the default 443).
Is it possible to achieve this via spring ?
thanks
Nohsib
Yes, it is possible to achieve using Spring Channel Processing and PortMapper
Spring Channel Processing used to define http/https access URL Patterns. For Example-
Https Access URL-
https://localhost/myapp/user/myaccount
Http: Access URL-
http://localhost/myapp/home
Then if user access the secure URL in http mode "http://localhost/myapp/user/myaccount" spring channel security redirect the user to secure URL "https://localhost/myapp/user/myaccount" and vice verse.
PortMapper Bean is used map non-standard port numbers for HTTP and HTTPS mapping
Sample Configuration:
Channel Processing Bean Definition And Port Mapper-
<bean id="channelProcessingFilter" class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
<property name="channelDecisionManager" ref="channelDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source path-type="ant">
<security:intercept-url pattern="/services/rest/nohisb/Msgs**" access="REQUIRES_SECURE_CHANNEL" />
<security:intercept-url pattern="/**/*.html**" access="REQUIRES_SECURE_CHANNEL" />
<!-- more pattern definition -->
</security:filter-security-metadata-source>
</property>
</bean>
<bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl">
<property name="channelProcessors">
<list>
<ref bean="secureChannelProcessor"/>
<ref bean="insecureChannelProcessor"/>
</list>
</property>
</bean>
<bean id="secureChannelProcessor" class="org.springframework.security.web.access.channel.SecureChannelProcessor">
<property name="entryPoint" ref="secureEntryPoint"/>
</bean>
<bean id="insecureChannelProcessor" class="org.springframework.security.web.access.channel.InsecureChannelProcessor">
<property name="entryPoint" ref="insecureEntryPoint"/>
</bean>
<bean id="secureEntryPoint" class="org.springframework.security.web.access.channel.RetryWithHttpsEntryPoint">
<property name="portMapper" ref="portMapper"/>
</bean>
<bean id="insecureEntryPoint" class="org.springframework.security.web.access.channel.RetryWithHttpEntryPoint">
<property name="portMapper" ref="portMapper"/>
</bean>
<bean id="portMapper" class="org.springframework.security.web.PortMapperImpl">
<property name="portMappings">
<map>
<entry key="80" value="443"/>
<entry key="8081" value="8443"/>
<entry key="8443" value="8081"/>
<!-- so on... -->
</map>
</property>
</bean>
Filter Mapping-
<security:http auto-config="false"
entry-point-ref="authenticationProcessingFilterEntryPoint"
access-decision-manager-ref="accessDecisionManager" >
<security:custom-filter position="CHANNEL_FILTER" ref="channelProcessingFilter"/>
<security:intercept-url pattern="/*.html*" access="ROLE_ANONYMOUS,admin,user" />
<security:intercept-url pattern="/*.jsp" access="ROLE_ANONYMOUS,admin,user" />
<!-- more pattern definition -->
</security:http>
You can write Servlet filter that will check request scheme and URL and sent redirect when needed.
But actually such stuff should be done not in the java code, but in a reverse proxy or balancer. Usually servlet container is used behind proxy (nginx?) or apache (mod_proxy) That's the place to configure https/http redirecting etc.
Wouldn't it be simpler to use the Spring Security namespace configuration as described in http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#ns-requires-channel to define port mappings?

Categories

Resources