2

I have spring web service and a business layer deployed separately on two tomcat servers. (As explained in the question Spring WS separately deploy web service and bussiness layer).

Business layer is just a servlet container and web service communicate with it spring httpinvoker.

I use tomcat container based authentication with springs PreAuthenticatedAuthenticationProvider and J2eePreAuthenticatedProcessingFilter. Here I does not provide client application with any authentication token. (I mean I am not manually doing any session handling. It is managed only by tomcat)

Now I want to make sure requests to my business layers are from a authenticated client. One thing I found is to pass the Authentication object which I get from the web service's security context as SecurityContextHolder.getContext().getAuthentication() as request parameter to the business layer. But there I do not have a way to verify that Authentication object. So any idea on a way to achieve security in my business layer?

Community
  • 1
  • 1
Thudani Hettimulla
  • 754
  • 1
  • 12
  • 32

1 Answers1

3

The httpinvoker way of remoting uses a http client, by default it wil use a plain HttpURLConnection from the JDK. Which way of connecting is used is determined by the imlementation of HttpInvokerRequestExecutor which by default is the SimpleHttpInvokerRequestExecutor.

Now you could switch to use one of the other implementations which use Apache Commons HttpClient under the hood. You could then use BASIC authentication (or digest) to pass the username/password to the service layer (instead of the Authentication object.

Spring Security already supplies this custom implementation for you, so basically the only thing you need to do (client side) is to reconfigure your HttpInvokerProxyFactoryBean.

<bean id="yourServiceProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    <property name="httpInvokerRequestExecutor" ref="requestExecutor" />
</bean>

<bean id="requestExecutor" class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor"/>

See also the javadoc and the Spring Security Reference Guide. This class can be found in the spring-security-remoting dependency. Next to this dependency you need to configure your business layer to use basic authentication.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Thank you. I have configured the web service and business layer as you mentioned. But for the business service also I used it as container based pre-authentication. Now I'am getting the error as Could not access HTTP invoker remote service at [http://localhost:8081/business-layer/Business]; nested exception is java.io.IOException: Did not receive successful HTTP response: status code = 401, status message = [Unauthorized]. Any idea on this? – Thudani Hettimulla Apr 11 '14 at 02:44
  • You should have the business side configured with BASIC authentication, this can all be done in Spring Security, so not sure why you would need container based pre-authentication for that. – M. Deinum Apr 11 '14 at 05:48
  • Thanks Denium. I could finally configure it after my vacation. Now it work fine. But I am looking whether there is a more elegant way to share the same security context between web service and business layer. So that user does not get authenticate twice. – Thudani Hettimulla Apr 16 '14 at 08:35
  • And that is a problem because? It is handled transparantly for the user and you don't want to enforce your backend to use Spring Security (what if you used tomcats basic authentication instead of spring security). It would also break if your client and server started to use different versions of Spring Security. You could use a SSO solution so that you could pass a SSO ticket with the request, but that is adding a lot of complexity. Your current solution is simple and works. – M. Deinum Apr 16 '14 at 08:51