source: josm/trunk/src/org/openstreetmap/josm/io/auth/AbstractCredentialsAgent.java

Last change on this file was 19345, checked in by stoecker, 13 months ago

don't send authentication oinformation to wrong server, fix #24149, patch by ssundell

  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io.auth;
3
4import java.net.Authenticator.RequestorType;
5import java.net.PasswordAuthentication;
6import java.util.HashMap;
7import java.util.Map;
8import java.util.Objects;
9
10import org.openstreetmap.josm.tools.Logging;
11import org.openstreetmap.josm.tools.Pair;
12
13/**
14 * Partial implementation of the {@link CredentialsAgent} interface.
15 * <p>
16 * Provides a memory cache for the credentials and means to query the information from the user.
17 * @since 4246
18 */
19public abstract class AbstractCredentialsAgent implements CredentialsAgent {
20
21 /**
22 * Synchronous credentials provider. Called if no credentials are cached. Can be used for user login prompt.
23 * @since 12821
24 */
25 @FunctionalInterface
26 public interface CredentialsProvider {
27 /**
28 * Fills the given response with appropriate user credentials.
29 * @param requestorType type of the entity requesting authentication
30 * @param agent the credentials agent requesting credentials
31 * @param response authentication response to fill
32 * @param username the known username, if any. Likely to be empty
33 * @param password the known password, if any. Likely to be empty
34 * @param host the host against authentication will be performed
35 */
36 void provideCredentials(RequestorType requestorType, AbstractCredentialsAgent agent, CredentialsAgentResponse response,
37 String username, String password, String host);
38 }
39
40 private static volatile CredentialsProvider credentialsProvider =
41 (a, b, c, d, e, f) -> Logging.error("Credentials provider has not been set");
42
43 /**
44 * Sets the global credentials provider.
45 * @param provider credentials provider. Called if no credentials are cached. Can be used for user login prompt
46 */
47 public static void setCredentialsProvider(CredentialsProvider provider) {
48 credentialsProvider = Objects.requireNonNull(provider, "provider");
49 }
50
51 protected Map<Pair<RequestorType, String>, PasswordAuthentication> memoryCredentialsCache = new HashMap<>();
52
53 @Override
54 public CredentialsAgentResponse getCredentials(final RequestorType requestorType, final String host, boolean noSuccessWithLastResponse)
55 throws CredentialsAgentException {
56 if (requestorType == null)
57 return null;
58 PasswordAuthentication credentials = lookup(requestorType, host);
59 final String username = (credentials == null || credentials.getUserName() == null) ? "" : credentials.getUserName();
60 final String password = (credentials == null || credentials.getPassword() == null) ? "" : String.valueOf(credentials.getPassword());
61
62 final CredentialsAgentResponse response = new CredentialsAgentResponse();
63
64 /*
65 * Last request was successful and there was no credentials stored in file (or only the username is stored).
66 * -> Try to recall credentials that have been entered manually in this session.
67 */
68 Pair<RequestorType, String> mccKey = Pair.create(requestorType, host);
69 if (!noSuccessWithLastResponse && memoryCredentialsCache.containsKey(mccKey) &&
70 (credentials == null || credentials.getPassword() == null || credentials.getPassword().length == 0)) {
71 PasswordAuthentication pa = memoryCredentialsCache.get(mccKey);
72 response.setUsername(pa.getUserName());
73 response.setPassword(pa.getPassword());
74 response.setCanceled(false);
75 /*
76 * Prompt the user for credentials. This happens the first time each
77 * josm start if the user does not save the credentials to preference
78 * file (username=="") and each time after authentication failed
79 * (noSuccessWithLastResponse == true).
80 */
81 } else if (noSuccessWithLastResponse || username.isEmpty() || password.isEmpty()) {
82 credentialsProvider.provideCredentials(requestorType, this, response, username, password, host);
83 if (response.isCanceled() || response.getUsername() == null || response.getPassword() == null) {
84 return response;
85 }
86 if (response.isSaveCredentials()) {
87 store(requestorType, host, new PasswordAuthentication(
88 response.getUsername(),
89 response.getPassword()
90 ));
91 } else {
92 // User decides not to save credentials to file. Keep it in memory so we don't have to ask over and over again.
93 memoryCredentialsCache.put(mccKey, new PasswordAuthentication(response.getUsername(), response.getPassword()));
94 }
95 } else {
96 // We got it from file.
97 response.setUsername(username);
98 response.setPassword(password.toCharArray());
99 response.setCanceled(false);
100 }
101 return response;
102 }
103
104 @Override
105 public final void purgeCredentialsCache(RequestorType requestorType) {
106 memoryCredentialsCache.keySet().removeIf(pair -> pair.a == requestorType);
107 }
108
109 @Override
110 public void purgeCredentialsCache(RequestorType requestorType, String host) {
111 memoryCredentialsCache.remove(Pair.create(requestorType, host));
112 }
113
114 /**
115 * Provide the text for a checkbox that offers to save the
116 * username and password that has been entered by the user.
117 * @return checkbox text
118 */
119 public abstract String getSaveUsernameAndPasswordCheckboxText();
120}
Note: See TracBrowser for help on using the repository browser.