Announcement Announcement Module
No announcement yet.
Web Services programatic authentication Page Title Module
Move Remove Collapse
This topic is closed
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Web Services programatic authentication

    We need to implement a secured web service, without passing credentials in every function call.

    We expose the login function via web service.
    It's implementation puts Authentication Object into the session

    _endPointContext.getHttpSession().setAttribute(Htt pSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTIC ATION_KEY, authResult);

    But in subsequent calls to web service we notice that the attribute value is missing from the session .(The key is still there).

    During debuging session I noticed that it get removed by the filter.
    After expirementing with the filter configuration we have discovered the minimum config that allows to reproduce it

    <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
    <filter-class>net.sf.acegisecurity.ui.AutoIntegrationFilte r</filter-class>
    <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>

    The question is why is the value removed from the session and how it can be avoided.

  • #2
    AutoIntegrationFilter, which usually delegates to HttpSessionIntegrationFilter, is responsible for:

    1. Reading the HttpSession attribute
    2. Writing it (the Authentication) to the ContextHolder
    3. Proceeding with the filter chain
    4. Reading the ContextHolder for the Authentication
    5. Writing the Authentication to the HttpSession

    During step 3 all classes interfacing with security should be doing so via the ContextHolder. In particular, AbstractSecurityInterceptor will re-validate any Authentication, refreshing GrantedAuthority[]s etc. We need to write it back to the HttpSession in step 5 because sometimes an AuthenticationProvider returns an Authentication that is fundamentally different from the original Authentication (eg the CasAuthenticationProvider).

    Regarding your usage, I'd recommend you to use the standard web services pattern with Acegi Security instead:

    - Present username and password with each request via the HTTP BASIC header
    - If you've got a login form on the client and want to check the credentials are correct before setting all the client proxies with a correct username/password (for BASIC authentication), use the net.sf.acegisecurity.providers.rcp (there's also a class in Spring Rich which automates the setting up of the client proxies: curityConfigurer)

    One bonus of this approach, aside from overcoming the problem you mentioned and using code maintained as part of the Acegi Security project, is that you need not worry about HttpSession maintenance across web services calls. The recommended approach is also highly efficient, as the authentication-related database hit each separate web services call may require is avoided via the UserCache used by DaoAuthenticationProvider (I'm assuming you're using DaoAuthenticationProvider).


    • #3
      Thank you for your reply.

      I'm still not clear about a few things.

      I understand that you have to rewrite the object in the session
      but it still doesn't explain why we get null instead of the valid object.

      The other approach you've suggested will also require rewrite of our client code.
      We have several clients on different platforms .Net and C++ so we'd
      like to avoid it if we can.

      So if you have other ideas or explanation for this I'd be glad to hear it.


      • #4
        Let me try to understand. You're writing an Authentication object directly to the HttpSession attribute keyed on HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHEN TICATION_KEY, but it gets set back to null by AutoIntegrationFilter at the end of each request?

        That's the expected behaviour, as per my earlier response.

        After re-reading your first post, the way I'd suggest you approach it is your "login" servlet sets the ContextHolder, not the HttpSession attribute. Then, as the "login" servlet is run within the filter chain of AutoIntegrationFilter, at the end of the AutoIntegrationFilter execution the ContextHolder contents will be copied to the appropriate HttpSession attribute. AFAICS it's a simple matter of you're setting the target location (HttpSession) when you should set the source location (ContextHolder), and then as expected the target gets overwritten with the source at the end of the filter chain.