0 Replies Latest reply on May 29, 2009 4:20 PM by mocha

    Hiding Conversation Id in Cookie

      cid appended to urls are screwing with my application's beauty, particularly during login redirect which is the first page that new users hit (and therefore bookmark).


      So I've come up with a possible solution which is to strip and store the cid in a cookie over a redirect.  Seems to work, but would be interested in feedback on the approach and if there is a better place to handle the coding of this. I couldn't see an easy place to deal with this in the seam framework, hence the filter approach.


      Worth pointing out that I have already disabled url based session identifiers for my app, so users can only login and use the system if they have cookies enabled.


      @Startup
      @Scope(ScopeType.APPLICATION)
      @Name("hideSeamCidFilter")
      @BypassInterceptors
      @Filter
      @Install(value = false, precedence = Install.APPLICATION)
      public class HideSeamCidFilter extends AbstractFilter {
      
          private class ParamHttpServletRequestWrapper extends HttpServletRequestWrapper {
      
              Map<String, String[]> params = new HashMap<String, String[]>();
      
              ParamHttpServletRequestWrapper(HttpServletRequest request) {
                  super(request);
              }
              ParamHttpServletRequestWrapper(HttpServletRequest request, Map<String, String> overrideParams) {
                  super(request);
                  params.putAll(request.getParameterMap());
                  for (Map.Entry<String, String> param:overrideParams.entrySet()) {
                      if (param.getValue()==null) {
                          params.put(param.getKey(), null);
                      } else {
                          String values[] = {param.getValue()};
                          params.put(param.getKey(), values);
                      }
                  }
              }
              @Override
              public String getParameter(String name) {
                  String[] value = params.get(name);
                  return (value==null || value.length == 0) ? null : value[0];
              }
              @Override
              public Map getParameterMap() {
                  return params;
              }
              @Override
              public Enumeration getParameterNames() {
                  return Collections.enumeration(params.keySet());
              }
              @Override
              public String[] getParameterValues(String name) {
                   return params.get(name);
              }
          }
      
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      
              if (!(request instanceof HttpServletRequest)) {
                  chain.doFilter(request, response);
                  return;
              }
      
              HttpServletRequest httpRequest = (HttpServletRequest) request;
              HttpServletResponse httpResponse = (HttpServletResponse) response;
      
              // check for conversation id stored in cookie
              String cid = null;
              if (httpRequest.getCookies() != null) {
                  for (Cookie cookie:httpRequest.getCookies()) {
                      if ("cid".equals(cookie.getName())) {
                          cid = cookie.getValue();
                          // now that we've got the cid we can clear it out of cookie - i.e. it's only valid for this request
                          cookie.setMaxAge(0);
                          httpResponse.addCookie(cookie);
                          break;
                      }
                  }
              }
      
              // if found, add conversationid to url parameters passed down to seam
              HashMap params = new HashMap();
              if (cid != null) { params.put("cid", cid); }
              HttpServletRequestWrapper wrappedRequest = new ParamHttpServletRequestWrapper(httpRequest, params);
      
      
              // override redirect requests from processing further down the line so that
              // conversation id can be stripped off redirect requests and stored in cookie
              HttpServletResponseWrapper wrappedResponse
                  = new HttpServletResponseWrapper(httpResponse)
              {
                  public void sendRedirect(String url) throws IOException
                  {
                      if (url.indexOf("cid=") > 0) {
                          // grab the cid
                          String cid = null;
                          int cidParamIndex = url.indexOf("cid=");
                          int nextParamIndex = url.indexOf("&", cidParamIndex);
                          if (nextParamIndex > 0) {
                              cid = url.substring(cidParamIndex+4, nextParamIndex);
                              // remove cid param leaving ? or & in place for next param
                              url = url.substring(0,cidParamIndex) + url.substring(nextParamIndex+1);
                          } else {
                              cid = url.substring(cidParamIndex+4, url.length());
                              url = url.substring(0,cidParamIndex-1);
                          }
                          
                          // add cid to cookie
                          Cookie cidCookie = new Cookie("cid", cid);
                          this.addCookie(cidCookie);
                      }
      
                      super.sendRedirect(url);
                   }
      
              };
      
              chain.doFilter(wrappedRequest, wrappedResponse);
          }
      }