1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient.auth;
31
32 import java.util.Collection;
33 import java.util.Iterator;
34 import java.util.Map;
35
36 import org.apache.commons.httpclient.params.HttpParams;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40 /***
41 * This class provides utility methods for processing HTTP www and proxy authentication
42 * challenges.
43 *
44 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
45 *
46 * @since 3.0
47 */
48 public final class AuthChallengeProcessor {
49
50 private static final Log LOG = LogFactory.getLog(AuthChallengeProcessor.class);
51
52 private HttpParams params = null;
53
54 /***
55 * Creates an authentication challenge processor with the given {@link HttpParams HTTP
56 * parameters}
57 *
58 * @param params the {@link HttpParams HTTP parameters} used by this processor
59 */
60 public AuthChallengeProcessor(final HttpParams params) {
61 super();
62 if (params == null) {
63 throw new IllegalArgumentException("Parameter collection may not be null");
64 }
65 this.params = params;
66 }
67
68 /***
69 * Determines the preferred {@link AuthScheme authentication scheme} that can be used
70 * to respond to the given collection of challenges.
71 *
72 * @param challenges the collection of authentication challenges
73 *
74 * @return the preferred {@link AuthScheme authentication scheme}
75 *
76 * @throws AuthChallengeException if the preferred authentication scheme
77 * cannot be determined or is not supported
78 */
79 public AuthScheme selectAuthScheme(final Map challenges) throws AuthChallengeException {
80 if (challenges == null) {
81 throw new IllegalArgumentException("Challenge map may not be null");
82 }
83 Collection authPrefs = (Collection) this.params.getParameter(
84 AuthPolicy.AUTH_SCHEME_PRIORITY);
85 if (authPrefs == null || authPrefs.isEmpty()) {
86 authPrefs = AuthPolicy.getDefaultAuthPrefs();
87 }
88 if (LOG.isDebugEnabled()) {
89 LOG.debug("Supported authentication schemes in the order of preference: "
90 + authPrefs);
91 }
92 AuthScheme authscheme = null;
93 String challenge = null;
94 Iterator item = authPrefs.iterator();
95 while (item.hasNext()) {
96 String id = (String) item.next();
97 challenge = (String) challenges.get(id.toLowerCase());
98 if (challenge != null) {
99 if (LOG.isInfoEnabled()) {
100 LOG.info(id + " authentication scheme selected");
101 }
102 try {
103 authscheme = AuthPolicy.getAuthScheme(id);
104 } catch (IllegalStateException e) {
105 throw new AuthChallengeException(e.getMessage());
106 }
107 break;
108 } else {
109 if (LOG.isDebugEnabled()) {
110 LOG.debug("Challenge for " + id + " authentication scheme not available");
111
112 }
113 }
114 }
115 if (authscheme == null) {
116
117 throw new AuthChallengeException(
118 "Unable to respond to any of these challenges: "
119 + challenges);
120 }
121 return authscheme;
122 }
123
124 /***
125 * Processes the given collection of challenges and updates the
126 * {@link AuthState state} of the authentication process.
127 *
128 * @param challenges the collection of authentication challenges
129 *
130 * @return the {@link AuthScheme authentication scheme} used to
131 * process the challenge
132 *
133 * @throws AuthChallengeException if authentication challenges cannot be
134 * successfully processed or the preferred authentication scheme cannot
135 * be determined
136 */
137 public AuthScheme processChallenge(final AuthState state, final Map challenges)
138 throws MalformedChallengeException, AuthenticationException
139 {
140 if (state == null) {
141 throw new IllegalArgumentException("Authentication state may not be null");
142 }
143 if (challenges == null) {
144 throw new IllegalArgumentException("Challenge map may not be null");
145 }
146
147 if (state.isPreemptive() || state.getAuthScheme() == null) {
148
149 state.setAuthScheme(selectAuthScheme(challenges));
150 }
151 AuthScheme authscheme = state.getAuthScheme();
152 String id = authscheme.getSchemeName();
153 if (LOG.isDebugEnabled()) {
154 LOG.debug("Using authentication scheme: " + id);
155 }
156 String challenge = (String) challenges.get(id.toLowerCase());
157 if (challenge == null) {
158 throw new AuthenticationException(id +
159 " authorization challenge expected, but not found");
160 }
161 authscheme.processChallenge(challenge);
162 LOG.debug("Authorization challenge processed");
163 return authscheme;
164 }
165 }