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 package org.apache.http.impl.client;
29
30 import java.util.Locale;
31 import java.util.Map;
32 import java.util.Queue;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.http.Header;
37 import org.apache.http.HttpHost;
38 import org.apache.http.HttpResponse;
39 import org.apache.http.auth.AuthProtocolState;
40 import org.apache.http.auth.AuthOption;
41 import org.apache.http.auth.AuthScheme;
42 import org.apache.http.auth.AuthState;
43 import org.apache.http.auth.MalformedChallengeException;
44 import org.apache.http.client.AuthenticationStrategy;
45 import org.apache.http.protocol.HttpContext;
46
47 public class HttpAuthenticator {
48
49 private final Log log;
50
51 public HttpAuthenticator(final Log log) {
52 super();
53 this.log = log != null ? log : LogFactory.getLog(getClass());
54 }
55
56 public HttpAuthenticator() {
57 this(null);
58 }
59
60 public boolean isAuthenticationRequested(
61 final HttpHost host,
62 final HttpResponse response,
63 final AuthenticationStrategy authStrategy,
64 final AuthState authState,
65 final HttpContext context) {
66 if (authStrategy.isAuthenticationRequested(host, response, context)) {
67 if (authState.getState() == AuthProtocolState.SUCCESS) {
68 authStrategy.authFailed(host, authState.getAuthScheme(), context);
69 }
70 this.log.debug("Authentication required");
71 return true;
72 } else {
73 switch (authState.getState()) {
74 case CHALLENGED:
75 case HANDSHAKE:
76 this.log.debug("Authentication succeeded");
77 authState.setState(AuthProtocolState.SUCCESS);
78 authStrategy.authSucceeded(host, authState.getAuthScheme(), context);
79 break;
80 case SUCCESS:
81 break;
82 default:
83 authState.setState(AuthProtocolState.UNCHALLENGED);
84 }
85 return false;
86 }
87 }
88
89 public boolean authenticate(
90 final HttpHost host,
91 final HttpResponse response,
92 final AuthenticationStrategy authStrategy,
93 final AuthState authState,
94 final HttpContext context) {
95 try {
96 if (this.log.isDebugEnabled()) {
97 this.log.debug(host.toHostString() + " requested authentication");
98 }
99 Map<String, Header> challenges = authStrategy.getChallenges(host, response, context);
100 if (challenges.isEmpty()) {
101 this.log.debug("Response contains no authentication challenges");
102 return false;
103 }
104
105 AuthScheme authScheme = authState.getAuthScheme();
106 switch (authState.getState()) {
107 case FAILURE:
108 return false;
109 case SUCCESS:
110 authState.reset();
111 break;
112 case CHALLENGED:
113 case HANDSHAKE:
114 if (authScheme == null) {
115 this.log.debug("Auth scheme is null");
116 authStrategy.authFailed(host, null, context);
117 authState.reset();
118 authState.setState(AuthProtocolState.FAILURE);
119 return false;
120 }
121 case UNCHALLENGED:
122 if (authScheme != null) {
123 String id = authScheme.getSchemeName();
124 Header challenge = challenges.get(id.toLowerCase(Locale.US));
125 if (challenge != null) {
126 this.log.debug("Authorization challenge processed");
127 authScheme.processChallenge(challenge);
128 if (authScheme.isComplete()) {
129 this.log.debug("Authentication failed");
130 authStrategy.authFailed(host, authState.getAuthScheme(), context);
131 authState.reset();
132 authState.setState(AuthProtocolState.FAILURE);
133 return false;
134 } else {
135 authState.setState(AuthProtocolState.HANDSHAKE);
136 return true;
137 }
138 } else {
139 authState.reset();
140
141 }
142 }
143 }
144 Queue<AuthOption> authOptions = authStrategy.select(challenges, host, response, context);
145 if (authOptions != null && !authOptions.isEmpty()) {
146 if (this.log.isDebugEnabled()) {
147 this.log.debug("Selected authentication options: " + authOptions);
148 }
149 authState.setState(AuthProtocolState.CHALLENGED);
150 authState.update(authOptions);
151 return true;
152 } else {
153 return false;
154 }
155 } catch (MalformedChallengeException ex) {
156 if (this.log.isWarnEnabled()) {
157 this.log.warn("Malformed challenge: " + ex.getMessage());
158 }
159 authState.reset();
160 return false;
161 }
162 }
163
164 }