From 245686954f67953e2dda80efc8c7a5c6d6b965e1 Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Wed, 22 Jul 2020 19:40:59 +0100 Subject: [PATCH] JAL-3633 Added Proxy Authentication credentials in Preferences and set via java.net.Authenticator --- src/jalview/bin/Cache.java | 226 +++++++++++++++++++++++++++-------- src/jalview/gui/Preferences.java | 81 ++++++++----- src/jalview/jbgui/GPreferences.java | 15 ++- 3 files changed, 241 insertions(+), 81 deletions(-) diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index 621b74b..6648099 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -29,6 +29,8 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; +import java.net.Authenticator; +import java.net.PasswordAuthentication; import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -276,7 +278,19 @@ public class Cache System.getProperty("http.proxyHost"), System.getProperty("http.proxyPort"), System.getProperty("https.proxyHost"), - System.getProperty("https.proxyPort") }; + System.getProperty("https.proxyPort"), + System.getProperty("http.proxyUser"), + System.getProperty("http.proxyPassword"), + System.getProperty("https.proxyUser"), + System.getProperty("https.proxyPassword"), + System.getProperty("http.nonProxyHosts") }; + + public final static String PROXYTYPE_NONE = "none"; + + // "false" and "true" for backward compatibility + public final static String PROXYTYPE_SYSTEM = "false"; + + public final static String PROXYTYPE_CUSTOM = "true"; /** Jalview Properties */ public static Properties applicationProperties = new Properties() @@ -412,34 +426,35 @@ public class Cache // PROXY TYPE settings (now three options "none", "false", "true", but using // backward compatible strings) - String proxyType = getDefault("USE_PROXY", "false"); + String proxyType = getDefault("USE_PROXY", PROXYTYPE_SYSTEM); // default to upgrading old settings switch (proxyType) { - case "none": - setProxyProperties(null, null, null, null); + case PROXYTYPE_NONE: + setProxyProperties(null, null, null, null, null, null, null, null); break; - case "false": // use system settings + case PROXYTYPE_SYSTEM: // use system settings resetProxyProperties(); break; - case "true": // use specified proxy settings + case PROXYTYPE_CUSTOM: // use specified proxy settings String httpHost = getDefault("PROXY_SERVER", ""); String httpPort = getDefault("PROXY_PORT", "8080"); String httpsHost = getDefault("PROXY_SERVER_HTTPS", httpHost); String httpsPort = getDefault("PROXY_PORT_HTTPS", httpPort); - setProxyProperties(httpHost, httpPort, httpsHost, httpsPort); + String httpUser = getDefault("PROXY_AUTH_USER", null); + String httpPassword = getDefault("PROXY_AUTH_PASSWORD", null); + // https.proxyUser and https.proxyPassword are not able to be + // independently set in Preferences yet + String httpsUser = getDefault("PROXY_AUTH_USER_HTTPS", httpUser); + String httpsPassword = getDefault("PROXY_AUTH_PASSWORD_HTTPS", + httpPassword); + setProxyProperties(httpHost, httpPort, httpsHost, httpsPort, httpUser, + httpPassword, httpsUser, httpsPassword); break; default: String message = "Incorrect PROXY_TYPE - should be 'none' (clear proxy properties), 'false' (system settings), 'true' (custom settings): " + proxyType; - if (Cache.log == null) - { - System.out.println(message); - } - else - { - Cache.log.warn(message); - } + Cache.warn(message); } // LOAD THE AUTHORS FROM THE authors.props file @@ -1256,72 +1271,183 @@ public class Cache public static void resetProxyProperties() { setProxyProperties(startupProxyProperties[0], startupProxyProperties[1], - startupProxyProperties[2], startupProxyProperties[3]); + startupProxyProperties[2], startupProxyProperties[3], + startupProxyProperties[4], startupProxyProperties[5], + startupProxyProperties[6], startupProxyProperties[7]); StringBuilder sb = new StringBuilder(); sb.append("Setting proxy properties to: http.proxyHost=") .append(startupProxyProperties[0]).append(", http.proxyPort=") - .append(startupProxyProperties[1]).append(", https.proxyHost=") - .append(startupProxyProperties[2]).append(", https.proxyPort=") - .append(startupProxyProperties[3]); - if (Cache.log == null) - { - System.err.println(sb.toString()); - } - else - { - Cache.log.debug(sb.toString()); - } + .append(startupProxyProperties[1]) + .append(startupProxyProperties[4] != null + && !startupProxyProperties[4].isEmpty() + ? " [" + startupProxyProperties[4] + "]" + : "") + .append(", https.proxyHost=").append(startupProxyProperties[2]) + .append(", https.proxyPort=").append(startupProxyProperties[3]) + .append(startupProxyProperties[6] != null + && !startupProxyProperties[6].isEmpty() + ? " [" + startupProxyProperties[6] + "]" + : ""); + + Cache.debug(sb.toString()); } - public static void setProxyProperties(String host, String port) + public static void setProxyProperties(String httpHost, String httpPort, + String httpsHost, String httpsPort, String httpUser, + String httpPassword) { - setProxyProperties(host, port, host, port); + setProxyProperties(httpHost, httpPort, httpsHost, httpsPort, httpUser, + httpPassword, httpUser, httpPassword); } public static void setProxyProperties(String httpHost, String httpPort, - String httpsHost, String httpsPort) + String httpsHost, String httpsPort, String httpUser, + String httpPassword, String httpsUser, String httpsPassword) { - // cannot set property to null -- use clearProperty instead - - // http.proxyHost - if (httpHost == null) + setOrClearSystemProperty("http.proxyHost", httpHost); + setOrClearSystemProperty("http.proxyPort", httpPort); + setOrClearSystemProperty("https.proxyHost", httpsHost); + setOrClearSystemProperty("https.proxyPort", httpsPort); + setOrClearSystemProperty("http.proxyUser", httpUser); + setOrClearSystemProperty("http.proxyPassword", httpPassword); + setOrClearSystemProperty("https.proxyUser", httpsUser); + setOrClearSystemProperty("https.proxyPassword", httpsPassword); + if (httpUser != null || httpsUser != null) { - System.clearProperty("http.proxyHost"); + try + { + Authenticator.setDefault(new Authenticator() + { + @Override + protected PasswordAuthentication getPasswordAuthentication() + { + if (getRequestorType() == RequestorType.PROXY) + { + try + { + if (getRequestingScheme().equalsIgnoreCase("http") + && getRequestingHost().equalsIgnoreCase(httpHost) + && getRequestingPort() == Integer.valueOf(httpPort)) + { + return new PasswordAuthentication(httpUser, + httpPassword == null ? new char[] {} + : httpPassword.toCharArray()); + } + if (getRequestingScheme().equalsIgnoreCase("https") + && getRequestingHost().equalsIgnoreCase(httpsHost) + && getRequestingPort() == Integer + .valueOf(httpsPort)) + { + return new PasswordAuthentication(httpsUser, + httpsPassword == null ? new char[] {} + : httpsPassword.toCharArray()); + } + } catch (NumberFormatException e) + { + Cache.error("Problem with proxy port values [http:" + + httpPort + ", https:" + httpsPort + "]"); + } + } + // non proxy request + return null; + } + }); + // required to re-enable basic authentication (should be okay for a + // local proxy) + System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); + } catch (SecurityException e) + { + Cache.error("Could not set default Authenticator"); + Cache.debug(getStackTraceString(e)); + } } else { - System.setProperty("http.proxyHost", httpHost); + // reset the Authenticator to protect http.proxyUser and + // http.proxyPassword Just In Case + Authenticator.setDefault(new Authenticator() + { + @Override + protected PasswordAuthentication getPasswordAuthentication() + { + return null; + } + }); } - // http.proxyPort - if (httpPort == null) + // clear localhost from proxying unless nonProxyHosts already set (not + // currently configurable in Preferences) + String nonProxyHosts = startupProxyProperties[8]; + System.setProperty("http.nonProxyHosts", + nonProxyHosts == null ? "localhost" : nonProxyHosts); + } + + public static void setOrClearSystemProperty(String key, String value) + { + if (key == null) + { + return; + } + if (value == null) { - System.clearProperty("http.proxyPort"); + System.clearProperty(key); } else { - System.setProperty("http.proxyPort", httpPort); + System.setProperty(key, value); } + } + + public final static int DEBUG = 10; + + public final static int INFO = 20; + + public final static int WARN = 30; - // https.proxyHost - if (httpsHost == null) + public final static int ERROR = 40; + + public static boolean println(int level, String message) + { + if (Cache.log == null) { - System.clearProperty("https.proxyHost"); + if (level >= ERROR) + System.err.println(message); + else + System.out.println(message); + return false; } - else + if (level >= WARN) { - System.setProperty("https.proxyHost", httpsHost); + Cache.log.warn(message); } - - // https.proxyPort - if (httpsPort == null) + else if (level >= INFO) { - System.clearProperty("https.proxyPort"); + Cache.log.info(message); } else { - System.setProperty("https.proxyPort", httpsPort); + Cache.log.debug(message); } + return true; + } + + public static void debug(String message) + { + println(DEBUG, message); + } + public static void info(String message) + { + println(INFO, message); + } + + public static void warn(String message) + { + println(WARN, message); + } + + public static void error(String message) + { + println(ERROR, message); } } diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index f337898..827c9a0 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -127,6 +127,8 @@ public class Preferences extends GPreferences private static final int MAX_FONT_SIZE = 30; + private String previousProxyType; + /** * Holds name and link separated with | character. Sequence ID must be * $SEQUENCE_ID$ or $SEQUENCE_ID=/.possible | chars ./=$ @@ -537,15 +539,16 @@ public class Preferences extends GPreferences } String proxyTypeString = Cache.getDefault("USE_PROXY", "false"); + previousProxyType = proxyTypeString; switch (proxyTypeString) { - case "none": + case Cache.PROXYTYPE_NONE: proxyType.setSelected(noProxy.getModel(), true); break; - case "false": + case Cache.PROXYTYPE_SYSTEM: proxyType.setSelected(systemProxy.getModel(), true); break; - case "true": + case Cache.PROXYTYPE_CUSTOM: proxyType.setSelected(customProxy.getModel(), true); break; default: @@ -557,6 +560,12 @@ public class Preferences extends GPreferences proxyPortHttpTB.setText(Cache.getDefault("PROXY_PORT", "")); proxyServerHttpsTB.setText(Cache.getDefault("PROXY_SERVER_HTTPS", "")); proxyPortHttpsTB.setText(Cache.getDefault("PROXY_PORT_HTTPS", "")); + proxyAuth.setSelected(Cache.getDefault("PROXY_AUTH", false)); + proxyAuthUsernameTB + .setText(Cache.getDefault("PROXY_AUTH_USERNAME", "")); + proxyAuthPasswordTB + .setText(Cache.getDefault("PROXY_AUTH_PASSWORD", "")); + setCustomProxyEnabled(); defaultBrowser.setText(Cache.getDefault("DEFAULT_BROWSER", "")); @@ -828,35 +837,20 @@ public class Preferences extends GPreferences Cache.applicationProperties.setProperty("DEFAULT_URL", sequenceUrlLinks.getPrimaryUrlId()); + // Proxy settings Cache.applicationProperties.setProperty("USE_PROXY", - customProxy.isSelected() ? "true" - : noProxy.isSelected() ? "none" : "false"); - + customProxy.isSelected() ? Cache.PROXYTYPE_CUSTOM + : noProxy.isSelected() ? Cache.PROXYTYPE_NONE + : Cache.PROXYTYPE_SYSTEM); Cache.setOrRemove("PROXY_SERVER", proxyServerHttpTB.getText()); - Cache.setOrRemove("PROXY_PORT", proxyPortHttpTB.getText()); - Cache.setOrRemove("PROXY_SERVER_HTTPS", proxyServerHttpsTB.getText()); - Cache.setOrRemove("PROXY_PORT_HTTPS", proxyPortHttpsTB.getText()); - - if (noProxy.isSelected()) - { - Cache.log.warn("Setting no proxy settings"); - Cache.setProxyProperties(null, null, null, null); - } - else if (customProxy.isSelected()) - { - Cache.log.warn("Setting custom proxy settings"); - Cache.setProxyProperties(proxyServerHttpTB.getText(), - proxyPortHttpTB.getText(), proxyServerHttpsTB.getText(), - proxyPortHttpsTB.getText()); - } - else // systemProxy should be selected and is sensible default - { - Cache.log.warn("Setting system proxy settings"); - Cache.resetProxyProperties(); - } + Cache.setOrRemove("PROXY_AUTH", + Boolean.toString(proxyAuth.isSelected())); + Cache.setOrRemove("PROXY_AUTH_USERNAME", proxyAuthUsernameTB.getText()); + Cache.setOrRemove("PROXY_AUTH_PASSWORD", proxyAuthPasswordTB.getText()); + setProxyFromSettings(); Cache.setProperty("VERSION_CHECK", Boolean.toString(versioncheck.isSelected())); @@ -954,6 +948,39 @@ public class Preferences extends GPreferences } } + public void setProxyFromSettings() + { + String proxyType = Cache.getDefault("USE_PROXY", + Cache.PROXYTYPE_SYSTEM); + if (proxyType.equals(Cache.PROXYTYPE_NONE)) + { + if (!previousProxyType.equals(proxyType)) + Cache.log.info("Setting no proxy settings"); + Cache.setProxyProperties(null, null, null, null, null, null, null, + null); + } + else if (proxyType.equals(Cache.PROXYTYPE_CUSTOM)) + { + if (!previousProxyType.equals(proxyType)) + Cache.log.info("Setting custom proxy settings"); + boolean proxyAuthSet = Cache.getDefault("PROXY_AUTH", false); + Cache.setProxyProperties(Cache.getDefault("PROXY_SERVER", null), + Cache.getDefault("PROXY_PORT", null), + Cache.getDefault("PROXY_SERVER_HTTPS", null), + Cache.getDefault("PROXY_PORT_HTTPS", null), + proxyAuthSet ? Cache.getDefault("PROXY_AUTH_USERNAME", "") + : null, + proxyAuthSet ? Cache.getDefault("PROXY_AUTH_PASSWORD", "") + : null); + } + else // systemProxy should be selected and is sensible default anyway + { + if (!previousProxyType.equals(proxyType)) + Cache.log.info("Setting system proxy settings"); + Cache.resetProxyProperties(); + } + } + /** * Do any necessary validation before saving settings. Return focus to the * first tab which fails validation. diff --git a/src/jalview/jbgui/GPreferences.java b/src/jalview/jbgui/GPreferences.java index ca5b203..67da0f4 100755 --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@ -961,9 +961,11 @@ public class GPreferences extends JPanel systemProxy.setFont(LABEL_FONT); systemProxy.setHorizontalAlignment(SwingConstants.LEFT); systemProxy.setText(MessageManager.formatMessage("label.system_proxy", - displayHostPort(Cache.startupProxyProperties[0], + displayUserHostPort(Cache.startupProxyProperties[4], + Cache.startupProxyProperties[0], Cache.startupProxyProperties[1]), - displayHostPort(Cache.startupProxyProperties[2], + displayUserHostPort(Cache.startupProxyProperties[6], + Cache.startupProxyProperties[2], Cache.startupProxyProperties[3]))); customProxy.setFont(LABEL_FONT); customProxy.setHorizontalAlignment(SwingConstants.LEFT); @@ -997,7 +999,6 @@ public class GPreferences extends JPanel }); setCustomProxyEnabled(); - setProxyAuthEnabled(); // Make proxy server panel JPanel proxyPanel = new JPanel(); @@ -1107,7 +1108,7 @@ public class GPreferences extends JPanel return proxyPanel; } - private String displayHostPort(String host, String port) + private String displayUserHostPort(String user, String host, String port) { boolean hostBlank = (host == null || host.isEmpty()); boolean portBlank = (port == null || port.isEmpty()); @@ -1117,6 +1118,12 @@ public class GPreferences extends JPanel } StringBuilder sb = new StringBuilder(); + if (user != null) + { + sb.append(user.isEmpty() || user.indexOf(" ") > -1 ? '"' + user + '"' + : user); + sb.append("@"); + } sb.append(hostBlank ? "" : host); if (!portBlank) { -- 1.7.10.2