Skip to content

Commit 5138cc1

Browse files
committed
Issue #281: Stop using Authenticator for Basic HTTP Auth
1 parent ecc027f commit 5138cc1

File tree

2 files changed

+121
-133
lines changed

2 files changed

+121
-133
lines changed

net.sf.eclipsecs.core/src/net/sf/eclipsecs/core/config/configtypes/RemoteConfigurationType.java

Lines changed: 115 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,14 @@
2929
import java.io.IOException;
3030
import java.io.InputStream;
3131
import java.io.UnsupportedEncodingException;
32-
import java.lang.reflect.Field;
33-
import java.net.Authenticator;
3432
import java.net.HttpURLConnection;
35-
import java.net.PasswordAuthentication;
3633
import java.net.URISyntaxException;
3734
import java.net.URL;
3835
import java.net.URLConnection;
3936
import java.net.UnknownHostException;
4037
import java.security.MessageDigest;
4138
import java.security.NoSuchAlgorithmException;
39+
import java.util.Base64;
4240
import java.util.HashSet;
4341
import java.util.Set;
4442

@@ -78,6 +76,9 @@ public class RemoteConfigurationType extends ConfigurationType {
7876
/** Key to access the password. */
7977
public static final String KEY_PASSWORD = "password"; //$NON-NLS-1$
8078

79+
/** Key to access the max redirect networking property. */
80+
public static final String KEY_MAX_REDIRECTS = "http.maxRedirects";
81+
8182
private static Set<String> sFailedWith401URLs = new HashSet<>();
8283

8384
/**
@@ -92,83 +93,85 @@ public CheckstyleConfigurationFile getCheckstyleConfiguration(
9293

9394
CheckstyleConfigurationFile data = new CheckstyleConfigurationFile();
9495

95-
synchronized (Authenticator.class) {
96-
97-
String currentRedirects = System.getProperty("http.maxRedirects"); //$NON-NLS-1$
98-
99-
Authenticator oldAuthenticator = RemoteConfigAuthenticator.getDefault();
100-
try {
101-
102-
// resolve the true configuration file URL
103-
data.setResolvedConfigFileURL(resolveLocation(checkConfiguration));
96+
final String currentRedirects = System.getProperty(KEY_MAX_REDIRECTS);
10497

105-
Authenticator.setDefault(new RemoteConfigAuthenticator(data.getResolvedConfigFileURL()));
106-
107-
boolean originalFileSuccess = false;
108-
byte[] configurationFileData = null;
98+
try {
10999

110-
try {
100+
// resolve the true configuration file URL
101+
data.setResolvedConfigFileURL(resolveLocation(checkConfiguration));
111102

112-
System.setProperty("http.maxRedirects", "3"); //$NON-NLS-1$ //$NON-NLS-2$
103+
boolean originalFileSuccess = false;
104+
byte[] configurationFileData = null;
113105

114-
URLConnection connection = data.getResolvedConfigFileURL().openConnection();
106+
try {
115107

116-
// get the configuration file data
117-
configurationFileData = getBytesFromURLConnection(connection);
108+
System.setProperty(KEY_MAX_REDIRECTS, "3");
118109

119-
// get last modification timestamp
120-
data.setModificationStamp(connection.getLastModified());
110+
final URLConnection connection = data.getResolvedConfigFileURL().openConnection();
121111

122-
originalFileSuccess = true;
123-
} catch (IOException e) {
124-
if (useCacheFile) {
125-
configurationFileData = getBytesFromCacheFile(checkConfiguration);
126-
} else {
127-
throw e;
128-
}
112+
final RemoteConfigAuthenticator auth = RemoteConfigAuthenticator.create(
113+
data.getResolvedConfigFileURL());
114+
if (auth != null) {
115+
connection.setRequestProperty("Authorization", auth.basicAuthHeaderValue);
129116
}
130117

131-
data.setCheckConfigFileBytes(configurationFileData);
118+
// get the configuration file data
119+
configurationFileData = getBytesFromURLConnection(connection);
120+
121+
// get last modification timestamp
122+
data.setModificationStamp(connection.getLastModified());
132123

133-
// get the properties bundle
134-
byte[] additionalPropertiesBytes = null;
135-
if (originalFileSuccess) {
136-
additionalPropertiesBytes = getAdditionPropertiesBundleBytes(
137-
data.getResolvedConfigFileURL());
138-
} else if (useCacheFile) {
139-
additionalPropertiesBytes = getBytesFromCacheBundleFile(checkConfiguration);
124+
originalFileSuccess = true;
125+
} catch (IOException exception) {
126+
if (useCacheFile) {
127+
configurationFileData = getBytesFromCacheFile(checkConfiguration);
128+
} else {
129+
throw exception;
140130
}
131+
}
141132

142-
data.setAdditionalPropertyBundleBytes(additionalPropertiesBytes);
133+
data.setCheckConfigFileBytes(configurationFileData);
143134

144-
// get the property resolver
145-
PropertyResolver resolver = getPropertyResolver(checkConfiguration, data);
146-
data.setPropertyResolver(resolver);
135+
// get the properties bundle
136+
byte[] additionalPropertiesBytes = null;
137+
if (originalFileSuccess) {
138+
additionalPropertiesBytes = getAdditionPropertiesBundleBytes(
139+
data.getResolvedConfigFileURL());
140+
} else if (useCacheFile) {
141+
additionalPropertiesBytes = getBytesFromCacheBundleFile(checkConfiguration);
142+
}
147143

148-
// write to cache file
149-
if (originalFileSuccess && useCacheFile) {
150-
writeToCacheFile(checkConfiguration, configurationFileData, additionalPropertiesBytes);
151-
}
144+
data.setAdditionalPropertyBundleBytes(additionalPropertiesBytes);
152145

153-
} catch (UnknownHostException e) {
154-
CheckstylePluginException.rethrow(e,
155-
NLS.bind(Messages.RemoteConfigurationType_errorUnknownHost, e.getMessage()));
156-
} catch (FileNotFoundException e) {
157-
CheckstylePluginException.rethrow(e,
158-
NLS.bind(Messages.RemoteConfigurationType_errorFileNotFound, e.getMessage()));
159-
} catch (IOException | URISyntaxException e) {
160-
CheckstylePluginException.rethrow(e);
161-
} finally {
162-
Authenticator.setDefault(oldAuthenticator);
146+
// get the property resolver
147+
final PropertyResolver resolver = getPropertyResolver(checkConfiguration, data);
148+
data.setPropertyResolver(resolver);
163149

164-
if (currentRedirects != null) {
165-
System.setProperty("http.maxRedirects", currentRedirects); //$NON-NLS-1$
166-
} else {
167-
System.getProperties().remove("http.maxRedirects"); //$NON-NLS-1$
168-
}
150+
// write to cache file
151+
if (originalFileSuccess && useCacheFile) {
152+
writeToCacheFile(checkConfiguration, configurationFileData, additionalPropertiesBytes);
169153
}
170154

171155
}
156+
catch (UnknownHostException exception) {
157+
CheckstylePluginException.rethrow(exception,
158+
NLS.bind(Messages.RemoteConfigurationType_errorUnknownHost, exception.getMessage()));
159+
}
160+
catch (FileNotFoundException exception) {
161+
CheckstylePluginException.rethrow(exception,
162+
NLS.bind(Messages.RemoteConfigurationType_errorFileNotFound, exception.getMessage()));
163+
}
164+
catch (IOException | URISyntaxException exception) {
165+
CheckstylePluginException.rethrow(exception);
166+
}
167+
finally {
168+
if (currentRedirects != null) {
169+
System.setProperty(KEY_MAX_REDIRECTS, currentRedirects);
170+
} else {
171+
System.getProperties().remove(KEY_MAX_REDIRECTS);
172+
}
173+
}
174+
172175
return data;
173176
}
174177

@@ -342,48 +345,61 @@ protected byte[] getBytesFromURLConnection(URLConnection connection) throws IOEx
342345
*
343346
* @author Lars Ködderitzsch
344347
*/
345-
public static class RemoteConfigAuthenticator extends Authenticator {
348+
public static final class RemoteConfigAuthenticator {
346349

347-
/** The check configuration URL. */
348-
private final URL mResolvedCheckConfigurationURL;
350+
/**
351+
* Username for HTTP Basic Auth.
352+
*/
353+
private final String username;
354+
/**
355+
* Password for HTTP Basic Auth.
356+
*/
357+
private final String password;
358+
/**
359+
* Basic Auth Header Value.
360+
*/
361+
private final String basicAuthHeaderValue;
349362

350363
/**
351-
* Creates the authenticator.
352-
*
353-
* @param resolvedCheckConfigurationURL
354-
* the check configuration URL
364+
* Creates a new RemoteConfigAuthenticator instance.
365+
* @param username Username for HTTP Basic Auth
366+
* @param password Password for HTTP Basic Auth
367+
* @param basicAuthHeaderValue Basic Auth Header Value
355368
*/
356-
public RemoteConfigAuthenticator(URL resolvedCheckConfigurationURL) {
357-
mResolvedCheckConfigurationURL = resolvedCheckConfigurationURL;
369+
private RemoteConfigAuthenticator(String username, String password,
370+
String basicAuthHeaderValue) {
371+
this.username = username;
372+
this.password = password;
373+
this.basicAuthHeaderValue = basicAuthHeaderValue;
358374
}
359375

360376
/**
361-
* Hacked together a piece of code to get the current default authenticator. Can't believe the
362-
* API is that bad...
377+
* Returns the stored authentication for the given check configuration URL.
363378
*
364-
* @return the current Authenticator
379+
* @param resolvedCheckConfigurationUrl
380+
* the configuration URL
381+
* @return the authentication object or <code>null</code> if none is stored
365382
*/
366-
public static Authenticator getDefault() {
367-
368-
Authenticator currentDefault = null;
369-
383+
public static RemoteConfigAuthenticator create(URL resolvedCheckConfigurationUrl) {
384+
RemoteConfigAuthenticator auth = null;
370385
try {
386+
final ISecurePreferences prefs = SecurePreferencesFactory.getDefault()
387+
.node(getSecureStoragePath(resolvedCheckConfigurationUrl));
371388

372-
// Hack to get the current authenticator
373-
Field[] fields = Authenticator.class.getDeclaredFields();
374-
for (int i = 0; i < fields.length; i++) {
375-
if (Authenticator.class.equals(fields[i].getType())) {
376-
fields[i].setAccessible(true);
377-
currentDefault = (Authenticator) fields[i].get(Authenticator.class);
378-
break;
379-
}
389+
final String userName = prefs.get(KEY_USERNAME, null);
390+
final String password = prefs.get(KEY_PASSWORD, null);
391+
392+
if (userName != null && password != null) {
393+
final String unencodedHeader = userName + ":" + password;
394+
final String basicAuthHeaderValue = "Basic " + Base64.getEncoder().encodeToString(
395+
unencodedHeader.getBytes());
396+
auth = new RemoteConfigAuthenticator(userName, password, basicAuthHeaderValue);
380397
}
381-
} catch (IllegalArgumentException e) {
382-
CheckstyleLog.log(e);
383-
} catch (IllegalAccessException e) {
384-
CheckstyleLog.log(e);
398+
} catch (CheckstylePluginException | StorageException exception) {
399+
CheckstyleLog.log(exception);
385400
}
386-
return currentDefault;
401+
402+
return auth;
387403
}
388404

389405
/**
@@ -416,43 +432,6 @@ public static void storeCredentials(URL resolvedCheckConfigurationURL, String us
416432
}
417433
}
418434

419-
@Override
420-
protected PasswordAuthentication getPasswordAuthentication() {
421-
return getPasswordAuthentication(mResolvedCheckConfigurationURL);
422-
}
423-
424-
/**
425-
* Returns the stored authentication for the given check configuration URL.
426-
*
427-
* @param resolvedCheckConfigurationURL
428-
* the configuration URL
429-
* @return the authentication object or <code>null</code> if none is stored
430-
*/
431-
public static PasswordAuthentication getPasswordAuthentication(
432-
URL resolvedCheckConfigurationURL) {
433-
434-
PasswordAuthentication auth = null;
435-
436-
try {
437-
438-
ISecurePreferences prefs = SecurePreferencesFactory.getDefault()
439-
.node(getSecureStoragePath(resolvedCheckConfigurationURL));
440-
441-
String userName = prefs.get(KEY_USERNAME, null);
442-
String password = prefs.get(KEY_PASSWORD, null);
443-
444-
if (userName != null && password != null) {
445-
auth = new PasswordAuthentication(userName, password.toCharArray());
446-
}
447-
} catch (CheckstylePluginException e) {
448-
CheckstyleLog.log(e);
449-
} catch (StorageException e) {
450-
CheckstyleLog.log(e);
451-
}
452-
453-
return auth;
454-
}
455-
456435
/**
457436
* Removes the authentication info from the session cache.
458437
*
@@ -498,5 +477,14 @@ private static String getSecureStoragePath(URL resolvedCheckConfigurationURL)
498477
}
499478
return "eclipse-cs/" + urlHash;
500479
}
480+
481+
public String getUsername() {
482+
return username;
483+
}
484+
485+
public String getPassword() {
486+
return password;
487+
}
488+
501489
}
502490
}

net.sf.eclipsecs.ui/src/net/sf/eclipsecs/ui/config/configtypes/RemoteConfigurationEditor.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020

2121
package net.sf.eclipsecs.ui.config.configtypes;
2222

23-
import com.google.common.base.Strings;
24-
2523
import java.net.MalformedURLException;
26-
import java.net.PasswordAuthentication;
2724
import java.net.URL;
2825

26+
import com.google.common.base.Strings;
27+
2928
import net.sf.eclipsecs.core.config.CheckConfigurationWorkingCopy;
3029
import net.sf.eclipsecs.core.config.configtypes.RemoteConfigurationType;
30+
import net.sf.eclipsecs.core.config.configtypes.RemoteConfigurationType.RemoteConfigAuthenticator;
3131
import net.sf.eclipsecs.core.util.CheckstylePluginException;
3232
import net.sf.eclipsecs.ui.CheckstyleUIPlugin;
3333
import net.sf.eclipsecs.ui.Messages;
@@ -193,11 +193,11 @@ public Control createEditorControl(Composite parent, final Shell shell) {
193193
if (mWorkingCopy.getLocation() != null) {
194194
try {
195195

196-
PasswordAuthentication auth = RemoteConfigurationType.RemoteConfigAuthenticator
197-
.getPasswordAuthentication(mWorkingCopy.getResolvedConfigurationFileURL());
196+
final RemoteConfigAuthenticator auth = RemoteConfigAuthenticator
197+
.create(mWorkingCopy.getResolvedConfigurationFileURL());
198198

199199
if (auth != null) {
200-
mUserName.setText(auth.getUserName());
200+
mUserName.setText(auth.getUsername());
201201
mPassword.setText(new String(auth.getPassword()));
202202
}
203203
} catch (CheckstylePluginException e) {

0 commit comments

Comments
 (0)