Bug 506395 - Improved cookie management
Summary: Improved cookie management
Status: NEW
Alias: None
Product: ECF
Classification: RT
Component: ecf.filetransfer (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: ecf.core-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-10-22 17:03 EDT by Ed Merks CLA
Modified: 2016-10-22 19:56 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Merks CLA 2016-10-22 17:03:48 EDT
One of the issues I encountered with using ECF in Oomph is servers that require not just basic authentication but authentication in conjunction with a cookie.  Unfortunately ECF's use of the underlying Apache frameworks is such that each access to the server creates a new cookie store. As such, the cookies returned by the server during previous interactions are not reused on subsequent communications with that server.

To work around this shortcoming, we have this type of hack in ECFURIHandlerImpl:

    private static void applyCookieStore(final IFileTransferConnectStartEvent connectStartEvent)
    {
      IIncomingFileTransfer fileTransfer = connectStartEvent.getAdapter(IIncomingFileTransfer.class);
      final IFileID fileID = connectStartEvent.getFileID();
      try
      {
        if (fileTransfer != null)
        {
          Object httpClient = ReflectUtil.getValue("httpClient", fileTransfer);
          ReflectUtil.setValue("cookieStore", httpClient, new org.apache.http.client.CookieStore()
          {
            @SuppressWarnings("all")
            public List<Cookie> getCookies()
            {
              return COOKIE_STORE.getCookies();
            }

            @SuppressWarnings("all")
            public boolean clearExpired(Date date)
            {
              synchronized (COOKIE_STORE)
              {
                List<Cookie> originalCookies = new ArrayList<Cookie>(COOKIE_STORE.getCookies());
                COOKIE_STORE.clearExpired(date);
                List<Cookie> remainingCookies = COOKIE_STORE.getCookies();
                originalCookies.removeAll(remainingCookies);

                for (Cookie cookie : originalCookies)
                {
                  ECFURIHandlerImpl.COOKIE_STORE.remove(null, new HttpCookie(cookie.getName(), cookie.getValue()));
                }

                return !originalCookies.isEmpty();
              }
            }

            @SuppressWarnings("all")
            public void clear()
            {
              COOKIE_STORE.clear();
              ECFURIHandlerImpl.COOKIE_STORE.removeAll();
            }

            @SuppressWarnings("all")
            public void addCookie(Cookie cookie)
            {
              try
              {
                java.net.URI uri = fileID.getURI();
                ECFURIHandlerImpl.COOKIE_STORE.add(uri, new HttpCookie(cookie.getName(), cookie.getValue()));
              }
              catch (Exception ex)
              {
                // Ignore bad information.
              }

              COOKIE_STORE.addCookie(cookie);
            }
          });
        }
      }
      catch (Throwable throwable)
      {
        // Ignore.
      }
    }
  }

Yes, it's very nasty but we set the cookie store field of the http client with an implementation that delegates to two global singleton cookie stores.  

We maintain on singleton cookie store here:

  private static final class FileTransferListener implements IFileTransferListener
  {
    @SuppressWarnings("all")
    private static final org.apache.http.impl.client.BasicCookieStore COOKIE_STORE = new org.apache.http.impl.client.BasicCookieStore();

As such, all communication with all servers delegate and hence use this single cookie store instance   

We also want to use java.net APIs so we have another global cookie store that uses java.net APIs.

  public static final CookieStore COOKIE_STORE = new CookieManager().getCookieStore();

That global cookie store we can use with SWT's browser to transfer the cookies we acquired with ECF (accessing Oomph setups), to the SWT browser for accessing secured links to the same server using established credentials and associated cookies.

    private void applyCookies()
    {
      List<java.net.URI> uris = ECFURIHandlerImpl.COOKIE_STORE.getURIs();
      for (java.net.URI cookieURI : uris)
      {
        String url = cookieURI.toString();
        for (HttpCookie httpCookie : ECFURIHandlerImpl.COOKIE_STORE.get(cookieURI))
        {
          Browser.setCookie(httpCookie.getValue(), url);
        }
      }
    }

I'm not sure what to suggest conceretely for ECF itself, but control over the cookie store used during communication, in particular the use of a global thread-safe singleton cookie store, would be very useful for communication that involves authentication in conjunction with cookies.  I.e., something that behaves more like a browser behaves, remembering cookies returned by a server and including those cookies in the headers of subsequent communication with that server...

Do you see what I'm getting at?
Comment 1 Scott Lewis CLA 2016-10-22 19:56:13 EDT
(In reply to Ed Merks from comment #0)
<stuff deleted>
> 
> Do you see what I'm getting at?

Yes.