Announcement Announcement Module
Collapse
No announcement yet.
Authenticate once and make multiple calls to services exported through HttpInvoker Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Authenticate once and make multiple calls to services exported through HttpInvoker

    Hi,

    I have the following scenario where an web application exposes a service (through HttpInvoker) and client applications consume this service. The client applications have to be authenticated first in order to use the exposed service and make calls.

    An web application exposes the serviceA by using HttpInvoker.

    <bean id="serviceA " class="..services.impl.serviceA" />

    <bean name="serviceAExporter" class="org.springframework.remoting.httpinvoker.Ht tpInvokerServiceExporter">
    <property name="service" ref="serviceA"/>
    <property name="serviceInterface" value="...services.serviceA "/>
    </bean>


    Also, the serviceA is using Spring Security:

    <security:http">
    <security:http-basic />
    <security:intercept-url pattern="/serviceA.service" access="ROLE_USER" />
    </security:http>


    and

    <security:authentication-manager> users,password, authorities... </security:authentication-manager>


    The client applications will invoke serviceA and methods of serviceA (e.g. serviceA.foo() ). In the beginning each client application will provide a username/password in order to authenticate.

    SecurityContextImpl sc = new SecurityContextImpl();
    Authentication auth = new UsernamePasswordAuthenticationToken(username,passw ord);
    sc.setAuthentication(auth);
    SecurityContextHolder.setContext(sc);


    and then


    ServiceA serviceA = (...) applicationContext.getBean("ServiceAHttpInvoker");
    serviceA.foo();
    serviceA.goo();
    ...other calls.


    In this case each call requires a new authentication check? Is it possible to authenticate once and all subsequent calls to skip the authentication? This means that once the client authenticates it will re-use somehow the session and we'll avoid the overhead of re-authentication for each call.

    thanks

  • #2
    Try using HTTPComponents-Executer on client side, instead of the simple default implementation from spring

    Code:
    	<bean name="serviceA" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    		<property name="serviceUrl" value="http://localhost:8080/yourApp/serviceA" />
    		<property name="serviceInterface" value="...services.serviceA " />
    		<property name="httpInvokerRequestExecutor" ref="httpComponentsHttpInvokerRequestExecutor" />
    	</bean>
    
    <bean id="httpComponentsHttpInvokerRequestExecutor" class="org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor" />
    if u use maven you can add the jar with
    <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.1.3</version>
    </dependency>

    Comment


    • #3
      thanks for your prompt response Matrium! I switched to the Apache HttpClient implementation but it doesn't work (it was OK with the previous default Spring impl. AuthenticationSimpleHttpInvokerRequestExecutor). I'll investigate further.

      Exception in thread "main" org.springframework.remoting.RemoteAccessException : Could not access HTTP invoker remote service at [http://localhost:8080/...serviceA.service]; nested exception is org.apache.http.NoHttpResponseException: Did not receive successful HTTP response: status code = 401, status message = [Unauthorized]

      My question is how HttpComponentsHttpInvokerRequestExecutor impl. solves the issue of re-authentication for each subsequent call. Could you provide further info on this please (documentation,url, etc...)?

      Comment


      • #4
        It's quite hard to find information on that topic for whatever reason. For the commons http client take a look at http://hc.apache.org/httpcomponents-...-ga/index.html

        What AuthenticationSimpleHttpInvokerRequestExecuter does is to send basic authentication with every request. That is ok if you want to build a REST-Service or something like that. But if full authentication envolves multiple steps (like authenticating with AD and queryin database for roles), it might be better to authenticate only once. You keep track of the session exactly the same way you would do in a webapplication--> use HTTP-session.

        If you are using Spring-Security 3.1 you could define 2 <http> elements. The first one requires no acces-role and is used for your login-service. The second is used for all other services, and requires ROLE_USER.
        Code:
        	<http pattern="/remoting/public/**" auto-config="true">
        		<intercept-url pattern="/**" method="POST"  requires-channel="https"/>
        	</http>
        
        	<http pattern="/**" auto-config="true">
        		<intercept-url pattern="/**" access="ROLE_USER" method="POST" requires-channel="https"/>
        	</http>
        You now should make sure that your LoginService is matched by the first element (otherwise you can't access it, because you can't have a role at that point). I published it like this.
        Code:
        <bean name="/public/loginService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        (note that my dispatcherservlets url-pattern is /remoting/* , could be different in your case)

        You then could use create-session="always" in the first <http> element. But probably the better way is to just create the session yourself in your authenticationProvider. I do it after everything went fine, that way i can ensure that no session is created for failed authentications. So bevore returning the authentication in your provider, just call request.getSession(); which automatically creates a session if none exists

        Comment


        • #5
          My problem now is that the authentication with HttpComponentsHttpInvokerRequestExecutor fails. When I revert this to AuthenticationSimpleHttpInvokerRequestExecutor it authenticates successfully.

          Exception in thread "main" org.springframework.remoting.RemoteAccessException : Could not access HTTP invoker remote service at [http://localhost:8080/.../...service]; nested exception is org.apache.http.NoHttpResponseException: Did not receive successful HTTP response: status code = 401, status message = [Unauthorized]

          Comment


          • #6
            Please post your server-side security configuration, at least your <http>-elment/elements

            As you get 401 the connection itself seems to be ok, maybe you still expect BasicAuth on every Post?

            Comment


            • #7
              Here it is.

              <security:http realm="TestSecurityRemoting">
              <security:intercept-url pattern="/**" access="ROLE_USER" />
              <security:http-basic/>
              </security:http>

              <security:authentication-manager>
              <security:authentication-provider>
              <security:user-service id="uds">
              <security:user name="testuser" password="testuser" authorities="ROLE_USER, ROLE_ADMIN" />
              </security:user-service>
              </security:authentication-provider>
              </security:authentication-manager>

              Comment


              • #8
                Well the missing configuration was the credentials of the HttpClient. After setting the credentials (org.apache.http.auth.UsernamePasswordCredentials) to the HttpClient the authentication/authorization
                works OK.

                Comment

                Working...
                X