Rajkumar Rajkumar - 5 months ago 61
Java Question

Getting 403 with POST method of Inbound Gateway - Spring Integration

So I have been trying to post some data to web service using Spring integration inbound gateway. GET method just works fine. So I tried to use POST, I'm passing some String. And trying to get a simple String as well. You can check the TestService. But everytime I try to run the Test case, I'm getting 403 error. I've checked Spring Security and every other aspect, but couldn't wrap my head around this. I googled for around 2 days but not a single clue about this.

You can look at THIS link, to see that my other functions which are GET methods and are working fine. I have this issue only with POST! So please help me out to know what is wrong with my code!

My integration.xml is :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:int-http="http://www.springframework.org/schema/integration/http">

<int:annotation-config/>

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json"/>
<property name="favorParameter" value="true"/>
<property name="ignoreAcceptHeader" value="true" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
</bean>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.integration.samples.rest.json.view.ExtendedMappingJacksonJsonView" >
<property name="objectMapper" ref="jaxbJacksonObjectMapper"/>
</bean>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg ref="marshaller"/>
</bean>
</list>
</property>
</bean>

<int:channel id="orderRequestChannel" />
<int:channel id="orderResponseChannel" />

<int-http:inbound-gateway id="inboundOrderRequestGateway"
supported-methods="POST"
request-channel="orderRequestChannel"
reply-channel="orderResponseChannel"
view-name="/order"
path="/order/view"
request-payload-type="java.lang.String"
reply-timeout="50000">
</int-http:inbound-gateway>

<int:service-activator id="orderGatewayActivator"
input-channel="orderRequestChannel"
output-channel="orderResponseChannel"
ref="testService"
method="createOrder"
requires-reply="true"
send-timeout="60000" />
<oxm:jaxb2-marshaller id="marshaller" context-path="org.springframework.integration.samples.rest.domain" />
<bean id="jaxbJacksonObjectMapper" class="org.springframework.integration.samples.rest.json.JaxbJacksonObjectMapper"/>


Test Service Method is :

@Service("testService")
public class TestService {

public Message<String> createOrder(Message<String> orderRequest) {
System.out.println("Inside!!!!!!!!!!");
return MessageBuilder.withPayload("Some Response!").build();
}
}


Spring Security File :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">

<security:global-method-security
secured-annotations="enabled" />

<!-- Configure Spring Security -->
<security:http auto-config="true" use-expressions="true" realm="REST HTTP Web Service" create-session="never">
<security:http-basic />
<security:intercept-url pattern='/services/employee/*' access="hasRole('ROLE_REST_HTTP_USER')" />
<security:intercept-url pattern='/order/*' access="permitAll" />
<security:csrf disabled="true" />
</security:http>

<!-- In this example, we are using in memory authentication. The password encoder depends on
Jasypt's String Digester to digest the password stored in users.properties -->
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<security:password-encoder ref="passwordEncoder"/>
<security:user-service properties="classpath:users.properties" />
</security:authentication-provider>
</security:authentication-manager>

<!--
Use the StringDigester to create uni-directional password encryption.
All uni-directional encryption methods supported in jasypt is integrated into
Spring Security
-->
<bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
<property name="algorithm" value="SHA-1" />
<property name="iterations" value="100000" />
<property name="saltGenerator">
<bean id="zeroSaltGenerator" class="org.jasypt.salt.ZeroSaltGenerator"/>
</property>
<property name="saltSizeBytes" value="10"/>
</bean>

<!--
This Spring Security-friendly PasswordEncoder implementation will
wrap the StringDigester instance so that it can be used from
the security framework.
-->
<bean id="passwordEncoder" class="org.jasypt.spring.security3.PasswordEncoder">
<property name="stringDigester" ref="jasyptStringDigester"/>
</bean>




Finally my test method :

@Test
public void testPOST() throws Exception{
final String fullUrl = "http://localhost:9080/rest-http/order/view";
HttpHeaders headers = new HttpHeaders();
HttpEntity<Object> request = new HttpEntity<Object>(headers);
ResponseEntity<?> httpResponse = restTemplate.exchange(fullUrl, HttpMethod.POST, request, String.class, "Request");
//restTemplate.getMessageConverters().add(jsonHttpMessageConverter);
if (!httpResponse.getStatusCode().equals(HttpStatus.OK)){
logger.error("Problems with the request. Http status: " + httpResponse.getStatusCode());
}

}


Please help me out guys!! Thanks in advance.

Answer

If you are using Spring's security then by default CSRF protection is enabled and a X-Csrf-Token is expected in the incoming request.

You have disable this adding below in your Spring security XML file. Read more here about Spring's CSRF protection and below code is discussed in section $16.4.2 Configure CSRF Protection

<http>
    <!-- ... -->
    <csrf disabled="false"/>
</http>
Comments