Announcement Announcement Module
Collapse
No announcement yet.
Embedding Extra Information in HttpInvoker invocation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Embedding Extra Information in HttpInvoker invocation

    hi,

    not too sure if this is the correct place to post this query. but would be glad if someone can provide some advice.

    usually when we do a HttpInvoker invocation, if we are using acegi security package, the username, and password would be send together with the invocation request.

    however, we do not know of a way to embed extra information such as user locale or other information transparently.

    what we are doing now is to put this Locale object as a argument to be passed to the server which i feel is not a good way to do this.

    instead of
    - find(int id, String name)
    we end up with
    - find(int id, String name, User user)
    in which user contains the locale.

    just like to know if anyone has a different view on this.

    thank you

  • #2
    Fortunately, HttpInvoker is a nice, extensible remoting protocol.

    I've just edited Acegi Security's AuthenticationSimpleHttpInvokerRequestExecutor so it has a doPrepareConnection method, which will be called after the BASIC authentication headers are set.

    You can now subclass the above class and set additional properties on the request for your locale. You can use the client-side Acegi Security ContextHolder to store your locale.

    On the server-side you'll need to write an extra filter that appears after the HttpSessionIntegrationFilter. This is because HttpSessionIntegrationFilter sets up the server-side ContextHolder with the Authentication put into the HttpSession by BasicProcessingFilter (BASIC authentication handler). There is a secureContext property on HttpSessionIntegrationFilter which enables you to specify the class you want created when the server-side ContextHolder is created.

    Your new filter would inspect the request headers and add an extra property to your server-side ContextHolder. This will be pretty easy by this stage, as the ContextHolder is setup and contains your custom SecureContext class. I'd suggest this custom class just subclasses SecureContextImpl.

    Comment


    • #3
      hi ben,

      thanks for you invaluable advice again. will try it out and if successful, will post the result here for others to reference.

      thanks a lot!

      Comment


      • #4
        hi,

        below is a writeup of how we implemented it.

        *** Client Side ***
        Code:
        BasicAuthenticationInvokerRequestExecutor
        ---------------------------------------------------
        private void embedInfo(final PostMethod postMethod){
        		Locale currentLocale = AppSession.getLocale();
        		postMethod.addRequestHeader("CURRENT_LOCALE_KEY", currentLocale.toString());		
        }
        ...
        protected RemoteInvocationResult doExecuteRequest(
        			final HttpInvokerClientConfiguration config,
        			final ByteArrayOutputStream baos) throws IOException,
        			ClassNotFoundException {
        ...	
        		PostMethod postMethod = createPostMethod(config);
        		
        		this.embedInfo(postMethod);
        ...
        *** Server Side ***
        Code:
        UserExtractionFilter 
        ----------------------
        public class UserExtractionFilter implements Filter{
        	
        	private static final Logger logger = Logger.getLogger(UserExtractionFilter.class);
        	private FilterConfig filterConfig;
        
        	private void setWmsSecureContext(String localeStr){
        		WmsSecureContext context = (WmsSecureContext)ContextHolder.getContext(); 
        		
        		//if(context==null)throw new GeneralException("Secure Context does not exists on server.");
        		if(context==null)return;
        		if(localeStr==null)return;
        		
        		String tokens[] = localeStr.split("_");
        		
        		logger.debug("tokens[0]: " + tokens[0]);
        		logger.debug("tokens[1]: " + tokens[1]);
        		
        		
        		
        		context.setCurrentLocale(new Locale(tokens[0], tokens[1]));		
        	}
        	
        	public void doFilter (ServletRequest request,
        	             ServletResponse response,
        	             FilterChain chain)
        	  {
        
        	    try
        	    {
        	    	if(!(request instanceof HttpServletRequest))
        	            throw new ServletException("Can only process HttpServletRequest");
        	        if(!(response instanceof HttpServletResponse))
        	            throw new ServletException("Can only process HttpServletResponse");
        	        
        	        HttpServletRequest httpRequest = (HttpServletRequest)request;
        	        HttpServletResponse httpResponse = (HttpServletResponse)response;
        	        String currentLocale = httpRequest.getHeader("CURRENT_LOCALE_KEY");
        	        	        	       
        	        logger.debug("context: " + ContextHolder.getContext());        
        	        logger.debug("CURRENT_LOCALE_KEY: " + currentLocale);
        	        
        	        this.setWmsSecureContext(currentLocale);	        
        
        	      chain.doFilter (request, response);	      
        	    } catch (IOException io) {
        	      System.out.println ("IOException raised in SimpleFilter");
        	    } catch (ServletException se) {
        	      System.out.println ("ServletException raised in SimpleFilter");
        	    }
        	  }
        
        	  public FilterConfig getFilterConfig()
        	  {
        	    return this.filterConfig;
        	  }
        
        	  public void setFilterConfig (FilterConfig filterConfig)
        	  {
        	    this.filterConfig = filterConfig;
        	  }
        
        	/* (non-Javadoc)
        	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
        	 */
        	public void init(FilterConfig arg0) throws ServletException {
        		// TODO Auto-generated method stub
        		this.setFilterConfig(arg0);
        	}
        
        	/* (non-Javadoc)
        	 * @see javax.servlet.Filter#destroy()
        	 */
        	public void destroy() {
        		// TODO Auto-generated method stub
        		
        	}
        
        }
        Code:
        Spring Config File
        ---------------------
        	<bean id="autoIntegrationFilter" class="net.sf.acegisecurity.ui.AutoIntegrationFilter">
        		<property name="secureContext"><value>com.web.WmsSecureContext</value></property>
        	</bean>
        Code:
        Retrieving the local object
        ------------------------------
        WmsSecureContext context = &#40;WmsSecureContext&#41;ContextHolder.getContext&#40;&#41;;
        Locale locale = context.getLocale&#40;&#41;;
        Conclusion
        ------------
        Embedding extra information wasn't too difficult once basic concepts was clear.
        Just need to add additional information in the header and then write a filter to create the desired object.
        However i wasn't able to use the AuthenticationSimpleHttpInvokerRequestExecutor because we are using CommonsHttpClient with SSL and there wasn't a method provided to extra header information.
        If the AuthenticationSimpleHttpInvokerRequestExecutor has these features, it would be great.


        once again, thanks ben for your advice.

        Comment

        Working...
        X