Changeset 9396 in josm


Ignore:
Timestamp:
2016-01-10T20:09:16+01:00 (9 years ago)
Author:
simon04
Message:

fix #7122 - Improve HTTP authentication for parallel requests (TMS/WMS imagery)

Location:
trunk/src/org/openstreetmap/josm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r9347 r9396  
    401401        }
    402402
    403         DefaultAuthenticator.createInstance();
    404403        Authenticator.setDefault(DefaultAuthenticator.getInstance());
    405404        DefaultProxySelector proxySelector = new DefaultProxySelector(ProxySelector.getDefault());
  • trunk/src/org/openstreetmap/josm/io/auth/DefaultAuthenticator.java

    r9313 r9396  
    44import java.net.Authenticator;
    55import java.net.PasswordAuthentication;
    6 import java.util.EnumMap;
    7 import java.util.Map;
     6import java.util.Collection;
     7import java.util.HashSet;
    88import java.util.Objects;
    99
    1010import org.openstreetmap.josm.Main;
    1111import org.openstreetmap.josm.io.OsmApi;
     12import org.openstreetmap.josm.tools.Pair;
    1213
    1314/**
     
    1718 */
    1819public final class DefaultAuthenticator extends Authenticator {
    19     private static volatile DefaultAuthenticator instance;
     20    private static final DefaultAuthenticator INSTANCE = new DefaultAuthenticator();
    2021
    2122    /**
     
    2425     */
    2526    public static DefaultAuthenticator getInstance() {
    26         return instance;
     27        return INSTANCE;
    2728    }
    2829
    29     /**
    30      * Creates the unique instance
    31      */
    32     public static void createInstance() {
    33         instance = new DefaultAuthenticator();
    34     }
    35 
    36     private final Map<RequestorType, Boolean> credentialsTried = new EnumMap<>(RequestorType.class);
     30    private final Collection<Pair<String, RequestorType>> failedCredentials = new HashSet<>();
    3731    private boolean enabled = true;
    3832
     
    5448                return null;
    5549            }
    56             boolean tried = credentialsTried.get(getRequestorType()) != null;
    57             CredentialsAgentResponse response = CredentialsManager.getInstance().getCredentials(getRequestorType(), getRequestingHost(), tried);
    58             if (response == null || response.isCanceled())
     50            final Pair<String, RequestorType> hostTypePair = Pair.create(getRequestingHost(), getRequestorType());
     51            final boolean hasFailedPreviously = failedCredentials.contains(hostTypePair);
     52            final CredentialsAgentResponse response = CredentialsManager.getInstance().getCredentials(
     53                    getRequestorType(), getRequestingHost(), hasFailedPreviously);
     54            if (response == null || response.isCanceled()) {
    5955                return null;
    60             credentialsTried.put(getRequestorType(), Boolean.TRUE);
     56            }
     57            if (RequestorType.PROXY.equals(getRequestorType())) {
     58                // Query user in case this authenticator is called (indicating that the authentication failed) the next time.
     59                failedCredentials.add(hostTypePair);
     60            } else {
     61                // Other parallel requests should not ask the user again, thus wait till this request is finished.
     62                // In case of invalid authentication, the host is added again to failedCredentials at HttpClient.connect()
     63                failedCredentials.remove(hostTypePair);
     64            }
    6165            return new PasswordAuthentication(response.getUsername(), response.getPassword());
    6266        } catch (CredentialsAgentException e) {
     
    6670    }
    6771
     72    /**
     73     * Determines whether this authenticator is enabled, i.e.,
     74     * provides {@link #getPasswordAuthentication() password authentication} via {@link CredentialsManager}.
     75     * @return whether this authenticator is enabled
     76     */
    6877    public boolean isEnabled() {
    6978        return enabled;
    7079    }
    7180
     81    /**
     82     * Enabled/disables this authenticator, i.e., decides whether it
     83     * should provide {@link #getPasswordAuthentication() password authentication} via {@link CredentialsManager}.
     84     * @param enabled whether this authenticator should be enabled
     85     */
    7286    public void setEnabled(boolean enabled) {
    7387        this.enabled = enabled;
    7488    }
     89
     90    /**
     91     * Marks for this host that the authentication failed, i.e.,
     92     * the {@link CredentialsManager} will show a dialog at the next time.
     93     * @param host the host to mark
     94     * @return as per {@link Collection#add(Object)}
     95     */
     96    public boolean addFailedCredentialHost(String host) {
     97        return failedCredentials.add(Pair.create(host, RequestorType.SERVER));
     98    }
     99
     100    /**
     101     * Un-marks the failed authentication attempt for the host
     102     * @param host the host to un-mark
     103     * @return as per {@link Collection#remove(Object)}
     104     */
     105    public boolean removeFailedCredentialHost(String host) {
     106        return failedCredentials.remove(Pair.create(host, RequestorType.SERVER));
     107    }
    75108}
  • trunk/src/org/openstreetmap/josm/tools/HttpClient.java

    r9314 r9396  
    2929import org.openstreetmap.josm.io.ProgressOutputStream;
    3030import org.openstreetmap.josm.io.UTFInputStreamReader;
     31import org.openstreetmap.josm.io.auth.DefaultAuthenticator;
    3132
    3233/**
     
    122123                if (Main.isDebugEnabled()) {
    123124                    Main.debug("RESPONSE: " + connection.getHeaderFields());
     125                }
     126                if (DefaultAuthenticator.getInstance().isEnabled() && connection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
     127                    DefaultAuthenticator.getInstance().addFailedCredentialHost(url.getHost());
    124128                }
    125129            } catch (IOException e) {
Note: See TracChangeset for help on using the changeset viewer.