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 package org.apache.hc.client5.http.impl.auth;
28
29 import java.io.IOException;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.io.Serializable;
33 import java.nio.charset.Charset;
34 import java.nio.charset.StandardCharsets;
35 import java.nio.charset.UnsupportedCharsetException;
36 import java.security.Principal;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Map;
41
42 import org.apache.commons.codec.binary.Base64;
43 import org.apache.hc.client5.http.auth.AuthChallenge;
44 import org.apache.hc.client5.http.auth.AuthScheme;
45 import org.apache.hc.client5.http.auth.StandardAuthScheme;
46 import org.apache.hc.client5.http.auth.AuthScope;
47 import org.apache.hc.client5.http.auth.AuthStateCacheable;
48 import org.apache.hc.client5.http.auth.AuthenticationException;
49 import org.apache.hc.client5.http.auth.Credentials;
50 import org.apache.hc.client5.http.auth.CredentialsProvider;
51 import org.apache.hc.client5.http.auth.MalformedChallengeException;
52 import org.apache.hc.client5.http.utils.ByteArrayBuilder;
53 import org.apache.hc.core5.http.HttpHost;
54 import org.apache.hc.core5.http.HttpRequest;
55 import org.apache.hc.core5.http.NameValuePair;
56 import org.apache.hc.core5.http.protocol.HttpContext;
57 import org.apache.hc.core5.util.Args;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61
62
63
64
65
66 @AuthStateCacheable
67 public class BasicScheme implements AuthScheme, Serializable {
68
69 private static final long serialVersionUID = -1931571557597830536L;
70
71 private static final Logger LOG = LoggerFactory.getLogger(BasicScheme.class);
72
73 private final Map<String, String> paramMap;
74 private transient Charset charset;
75 private transient ByteArrayBuilder buffer;
76 private transient Base64 base64codec;
77 private boolean complete;
78
79 private String username;
80 private char[] password;
81
82
83
84
85 public BasicScheme(final Charset charset) {
86 this.paramMap = new HashMap<>();
87 this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
88 this.complete = false;
89 }
90
91 public BasicScheme() {
92 this(StandardCharsets.US_ASCII);
93 }
94
95 public void initPreemptive(final Credentials credentials) {
96 if (credentials != null) {
97 this.username = credentials.getUserPrincipal().getName();
98 this.password = credentials.getPassword();
99 } else {
100 this.username = null;
101 this.password = null;
102 }
103 }
104
105 @Override
106 public String getName() {
107 return StandardAuthScheme.BASIC;
108 }
109
110 @Override
111 public boolean isConnectionBased() {
112 return false;
113 }
114
115 @Override
116 public String getRealm() {
117 return this.paramMap.get("realm");
118 }
119
120 @Override
121 public void processChallenge(
122 final AuthChallenge authChallenge,
123 final HttpContext context) throws MalformedChallengeException {
124 this.paramMap.clear();
125 final List<NameValuePair> params = authChallenge.getParams();
126 if (params != null) {
127 for (final NameValuePair param: params) {
128 this.paramMap.put(param.getName().toLowerCase(Locale.ROOT), param.getValue());
129 }
130 }
131 this.complete = true;
132 }
133
134 @Override
135 public boolean isChallengeComplete() {
136 return this.complete;
137 }
138
139 @Override
140 public boolean isResponseReady(
141 final HttpHost host,
142 final CredentialsProvider credentialsProvider,
143 final HttpContext context) throws AuthenticationException {
144
145 Args.notNull(host, "Auth host");
146 Args.notNull(credentialsProvider, "CredentialsProvider");
147
148 final AuthScopep/auth/AuthScope.html#AuthScope">AuthScope authScope = new AuthScope(host, getRealm(), getName());
149 final Credentials credentials = credentialsProvider.getCredentials(
150 authScope, context);
151 if (credentials != null) {
152 this.username = credentials.getUserPrincipal().getName();
153 this.password = credentials.getPassword();
154 return true;
155 }
156
157 LOG.debug("No credentials found for auth scope [{}]", authScope);
158 this.username = null;
159 this.password = null;
160 return false;
161 }
162
163 @Override
164 public Principal getPrincipal() {
165 return null;
166 }
167
168 @Override
169 public String generateAuthResponse(
170 final HttpHost host,
171 final HttpRequest request,
172 final HttpContext context) throws AuthenticationException {
173 if (this.buffer == null) {
174 this.buffer = new ByteArrayBuilder(64).charset(this.charset);
175 } else {
176 this.buffer.reset();
177 }
178 this.buffer.append(this.username).append(":").append(this.password);
179 if (this.base64codec == null) {
180 this.base64codec = new Base64(0);
181 }
182 final byte[] encodedCreds = this.base64codec.encode(this.buffer.toByteArray());
183 this.buffer.reset();
184 return StandardAuthScheme.BASIC + " " + new String(encodedCreds, 0, encodedCreds.length, StandardCharsets.US_ASCII);
185 }
186
187 private void writeObject(final ObjectOutputStream out) throws IOException {
188 out.defaultWriteObject();
189 out.writeUTF(this.charset.name());
190 }
191
192 @SuppressWarnings("unchecked")
193 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
194 in.defaultReadObject();
195 try {
196 this.charset = Charset.forName(in.readUTF());
197 } catch (final UnsupportedCharsetException ex) {
198 this.charset = StandardCharsets.US_ASCII;
199 }
200 }
201
202 private void readObjectNoData() {
203 }
204
205 @Override
206 public String toString() {
207 return getName() + this.paramMap;
208 }
209
210 }