Skip to content

Commit 68c9e7a

Browse files
author
oleksiys
committed
[1.9.x] + move perConnection and perRequest authentication methods to com.ning.util.AuthenticationUtils and use them in Grizzly provider
1 parent 3d906fd commit 68c9e7a

File tree

7 files changed

+211
-145
lines changed

7 files changed

+211
-145
lines changed

src/main/java/com/ning/http/client/providers/grizzly/AsyncHttpClientFilter.java

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import java.util.List;
3737
import java.util.Map;
3838
import org.glassfish.grizzly.Connection;
39+
import org.glassfish.grizzly.Grizzly;
40+
import org.glassfish.grizzly.attributes.Attribute;
3941
import org.glassfish.grizzly.filterchain.BaseFilter;
4042
import org.glassfish.grizzly.filterchain.FilterChainContext;
4143
import org.glassfish.grizzly.filterchain.FilterChainEvent;
@@ -61,6 +63,10 @@
6163
final class AsyncHttpClientFilter extends BaseFilter {
6264
private final static Logger LOGGER = LoggerFactory.getLogger(AsyncHttpClientFilter.class);
6365

66+
private final static Attribute<Boolean> USED_CONNECTION =
67+
Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute(
68+
AsyncHttpClientFilter.class.getName() + ".used-connection");
69+
6470
// Lazy NTLM instance holder
6571
private static class NTLM_INSTANCE_HOLDER {
6672
private final static NTLMEngine ntlmEngine = new NTLMEngine();
@@ -104,6 +110,13 @@ public NextAction handleEvent(final FilterChainContext ctx, final FilterChainEve
104110

105111
private boolean sendAsGrizzlyRequest(final HttpTransactionContext httpTxCtx, final FilterChainContext ctx) throws IOException {
106112
final Connection connection = ctx.getConnection();
113+
114+
final boolean isUsedConnection = Boolean.TRUE.equals(USED_CONNECTION.get(connection));
115+
if (!isUsedConnection) {
116+
USED_CONNECTION.set(connection, Boolean.TRUE);
117+
}
118+
119+
107120
final Request ahcRequest = httpTxCtx.getAhcRequest();
108121
if (isUpgradeRequest(httpTxCtx.getAsyncHandler()) && isWSRequest(httpTxCtx.requestUri)) {
109122
httpTxCtx.isWSRequest = true;
@@ -120,7 +133,7 @@ private boolean sendAsGrizzlyRequest(final HttpTransactionContext httpTxCtx, fin
120133
// once the tunnel is established, sendAsGrizzlyRequest will
121134
// be called again and we'll finally send the request over the tunnel
122135
return establishConnectTunnel(proxy, httpTxCtx, uri, ctx);
123-
}
136+
}
124137
final HttpRequestPacket.Builder builder = HttpRequestPacket.builder().protocol(Protocol.HTTP_1_1).method(method);
125138

126139
if (useProxy && !((secure || httpTxCtx.isWSRequest) &&
@@ -164,9 +177,14 @@ private boolean sendAsGrizzlyRequest(final HttpTransactionContext httpTxCtx, fin
164177
addHostHeaderIfNeeded(ahcRequest, uri, requestPacket);
165178
addServiceHeaders(requestPacket);
166179
addAcceptHeaders(requestPacket);
167-
addAuthorizationHeader(connection, getRealm(ahcRequest), requestPacket);
180+
181+
final Realm realm = getRealm(ahcRequest);
182+
addAuthorizationHeader(ahcRequest, requestPacket, realm,
183+
uri, proxy, isUsedConnection);
184+
168185
if (useProxy) {
169-
addProxyHeaders(proxy, requestPacket);
186+
addProxyHeaders(ahcRequest, requestPacket, realm, proxy,
187+
isUsedConnection, false);
170188
}
171189

172190
ctx.notifyDownstream(new SSLSwitchingEvent(connection, secure,
@@ -193,8 +211,10 @@ private boolean establishConnectTunnel(final ProxyServer proxy,
193211
final Request request = httpCtx.getAhcRequest();
194212
addHostHeaderIfNeeded(request, uri, requestPacket);
195213
addServiceHeaders(requestPacket);
196-
addAuthorizationHeader(connection, getRealm(request), requestPacket);
197-
addProxyHeaders(proxy, requestPacket);
214+
215+
final Realm realm = getRealm(request);
216+
addAuthorizationHeader(request, requestPacket, realm, uri, proxy, false);
217+
addProxyHeaders(request, requestPacket, realm, proxy, false, true);
198218

199219
// turn off SSL, because CONNECT will be sent in plain mode
200220
ctx.notifyDownstream(new SSLSwitchingEvent(connection, false));
@@ -265,22 +285,57 @@ private boolean isPayloadAllowed(final Method method) {
265285
return method.getPayloadExpectation() != Method.PayloadExpectation.NOT_ALLOWED;
266286
}
267287

268-
private void addAuthorizationHeader(final Connection c, final Realm realm, final HttpRequestPacket requestPacket) {
269-
if (realm != null && realm.getUsePreemptiveAuth()) {
270-
final String authHeaderValue = generateAuthHeader(c, realm);
271-
if (authHeaderValue != null) {
272-
requestPacket.addHeader(Header.Authorization, authHeaderValue);
288+
private void addAuthorizationHeader(final Request req,
289+
final HttpRequestPacket requestPacket,
290+
final Realm realm,
291+
final Uri uri, ProxyServer proxy,
292+
final boolean isUsedConnection) throws IOException {
293+
294+
if (!isUsedConnection) {
295+
final String conAuth =
296+
AuthenticatorUtils.perConnectionAuthorizationHeader(
297+
req, uri, proxy, realm);
298+
if (conAuth != null) {
299+
requestPacket.addHeader(Header.Authorization, conAuth);
273300
}
274301
}
302+
303+
final String reqAuth = AuthenticatorUtils.perRequestAuthorizationHeader(
304+
req, uri, realm);
305+
if (reqAuth != null) {
306+
requestPacket.addHeader(Header.Authorization, reqAuth);
307+
}
275308
}
276309

277-
private void addProxyHeaders(final ProxyServer proxy,
278-
final HttpRequestPacket requestPacket) {
310+
private void addProxyHeaders(
311+
final Request req,
312+
final HttpRequestPacket requestPacket,
313+
final Realm realm,
314+
final ProxyServer proxy,
315+
final boolean isUsedConnection,
316+
final boolean isConnect) throws IOException {
279317

280318
setKeepAliveForHeader(Header.ProxyConnection, requestPacket);
319+
setProxyAuthorizationHeader(req, requestPacket, proxy, realm,
320+
isUsedConnection, isConnect);
321+
}
322+
323+
private void setProxyAuthorizationHeader(final Request req, final HttpRequestPacket requestPacket, final ProxyServer proxy, final Realm realm, final boolean isUsedConnection, final boolean isConnect) throws IOException {
324+
final String reqAuth = AuthenticatorUtils.perRequestProxyAuthorizationHeader(
325+
req, realm, proxy, isConnect);
326+
327+
if (reqAuth != null) {
328+
requestPacket.setHeader(Header.ProxyAuthorization, reqAuth);
329+
return;
330+
}
281331

282-
if (proxy.getPrincipal() != null) {
283-
requestPacket.setHeader(Header.ProxyAuthorization, AuthenticatorUtils.computeBasicAuthentication(proxy));
332+
if (!isUsedConnection) {
333+
final String conAuth =
334+
AuthenticatorUtils.perConnectionProxyAuthorizationHeader(
335+
req, proxy, isConnect);
336+
if (conAuth != null) {
337+
requestPacket.setHeader(Header.ProxyAuthorization, conAuth);
338+
}
284339
}
285340
}
286341

src/main/java/com/ning/http/client/providers/netty/handler/HttpProtocol.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
import com.ning.http.client.providers.netty.response.NettyResponseBodyPart;
4848
import com.ning.http.client.providers.netty.response.NettyResponseHeaders;
4949
import com.ning.http.client.providers.netty.response.NettyResponseStatus;
50-
import com.ning.http.client.providers.netty.spnego.SpnegoEngine;
50+
import com.ning.http.client.spnego.SpnegoEngine;
5151
import com.ning.http.client.uri.Uri;
5252

5353
import java.io.IOException;

src/main/java/com/ning/http/client/providers/netty/request/NettyRequestFactory.java

Lines changed: 4 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
package com.ning.http.client.providers.netty.request;
1515

1616
import static com.ning.http.client.providers.netty.ws.WebSocketUtils.getKey;
17-
import static com.ning.http.util.AsyncHttpProviderUtils.DEFAULT_CHARSET;
1817
import static com.ning.http.util.AsyncHttpProviderUtils.*;
19-
import static com.ning.http.util.AuthenticatorUtils.computeBasicAuthentication;
20-
import static com.ning.http.util.AuthenticatorUtils.computeDigestAuthentication;
18+
import static com.ning.http.util.AuthenticatorUtils.perRequestAuthorizationHeader;
19+
import static com.ning.http.util.AuthenticatorUtils.perRequestProxyAuthorizationHeader;
2120
import static com.ning.http.util.MiscUtils.isNonEmpty;
2221

2322
import org.jboss.netty.buffer.ChannelBuffer;
@@ -30,12 +29,10 @@
3029
import com.ning.http.client.AsyncHttpClientConfig;
3130
import com.ning.http.client.ProxyServer;
3231
import com.ning.http.client.Realm;
33-
import com.ning.http.client.Realm.AuthScheme;
3432
import com.ning.http.client.Request;
3533
import com.ning.http.client.cookie.CookieEncoder;
3634
import com.ning.http.client.generators.FileBodyGenerator;
3735
import com.ning.http.client.generators.InputStreamBodyGenerator;
38-
import com.ning.http.client.ntlm.NTLMEngine;
3936
import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig;
4037
import com.ning.http.client.providers.netty.request.body.NettyBody;
4138
import com.ning.http.client.providers.netty.request.body.NettyBodyBody;
@@ -46,7 +43,6 @@
4643
import com.ning.http.client.providers.netty.request.body.NettyFileBody;
4744
import com.ning.http.client.providers.netty.request.body.NettyInputStreamBody;
4845
import com.ning.http.client.providers.netty.request.body.NettyMultipartBody;
49-
import com.ning.http.client.providers.netty.spnego.SpnegoEngine;
5046
import com.ning.http.client.uri.Uri;
5147
import com.ning.http.util.StringUtils;
5248

@@ -94,120 +90,6 @@ private String hostHeader(Request request, Uri uri) {
9490
}
9591
}
9692

97-
public String firstRequestOnlyAuthorizationHeader(Request request, Uri uri, ProxyServer proxyServer, Realm realm) throws IOException {
98-
String authorizationHeader = null;
99-
100-
if (realm != null && realm.getUsePreemptiveAuth()) {
101-
switch (realm.getScheme()) {
102-
case NTLM:
103-
String msg = NTLMEngine.INSTANCE.generateType1Msg();
104-
authorizationHeader = "NTLM " + msg;
105-
break;
106-
case KERBEROS:
107-
case SPNEGO:
108-
String host;
109-
if (proxyServer != null)
110-
host = proxyServer.getHost();
111-
else if (request.getVirtualHost() != null)
112-
host = request.getVirtualHost();
113-
else
114-
host = uri.getHost();
115-
116-
try {
117-
authorizationHeader = "Negotiate " + SpnegoEngine.INSTANCE.generateToken(host);
118-
} catch (Throwable e) {
119-
throw new IOException(e);
120-
}
121-
break;
122-
default:
123-
break;
124-
}
125-
}
126-
127-
return authorizationHeader;
128-
}
129-
130-
private String systematicAuthorizationHeader(Request request, Uri uri, Realm realm) {
131-
132-
String authorizationHeader = null;
133-
134-
if (realm != null && realm.getUsePreemptiveAuth() && !realm.isTargetProxy()) {
135-
136-
switch (realm.getScheme()) {
137-
case BASIC:
138-
authorizationHeader = computeBasicAuthentication(realm);
139-
break;
140-
case DIGEST:
141-
if (isNonEmpty(realm.getNonce()))
142-
authorizationHeader = computeDigestAuthentication(realm);
143-
break;
144-
case NTLM:
145-
case KERBEROS:
146-
case SPNEGO:
147-
// NTLM, KERBEROS and SPNEGO are only set on the first request, see firstRequestOnlyAuthorizationHeader
148-
case NONE:
149-
break;
150-
default:
151-
throw new IllegalStateException("Invalid Authentication " + realm);
152-
}
153-
}
154-
155-
return authorizationHeader;
156-
}
157-
158-
public String firstRequestOnlyProxyAuthorizationHeader(Request request, ProxyServer proxyServer, boolean connect) throws IOException {
159-
String proxyAuthorization = null;
160-
161-
if (connect) {
162-
List<String> auth = request.getHeaders().get(HttpHeaders.Names.PROXY_AUTHORIZATION);
163-
String ntlmHeader = getNTLM(auth);
164-
if (ntlmHeader != null) {
165-
proxyAuthorization = ntlmHeader;
166-
}
167-
168-
} else if (proxyServer != null && proxyServer.getPrincipal() != null && isNonEmpty(proxyServer.getNtlmDomain())) {
169-
List<String> auth = request.getHeaders().get(HttpHeaders.Names.PROXY_AUTHORIZATION);
170-
if (getNTLM(auth) == null) {
171-
String msg = NTLMEngine.INSTANCE.generateType1Msg();
172-
proxyAuthorization = "NTLM " + msg;
173-
}
174-
}
175-
176-
return proxyAuthorization;
177-
}
178-
179-
private String systematicProxyAuthorizationHeader(Request request, Realm realm, ProxyServer proxyServer, boolean connect) {
180-
181-
String proxyAuthorization = null;
182-
183-
if (!connect && proxyServer != null && proxyServer.getPrincipal() != null
184-
&& proxyServer.getScheme() == AuthScheme.BASIC) {
185-
proxyAuthorization = computeBasicAuthentication(proxyServer);
186-
187-
} else if (realm != null && realm.getUsePreemptiveAuth() && realm.isTargetProxy()) {
188-
189-
switch (realm.getScheme()) {
190-
case BASIC:
191-
proxyAuthorization = computeBasicAuthentication(realm);
192-
break;
193-
case DIGEST:
194-
if (isNonEmpty(realm.getNonce()))
195-
proxyAuthorization = computeDigestAuthentication(realm);
196-
break;
197-
case NTLM:
198-
case KERBEROS:
199-
case SPNEGO:
200-
// NTLM, KERBEROS and SPNEGO are only set on the first request, see firstRequestOnlyAuthorizationHeader
201-
case NONE:
202-
break;
203-
default:
204-
throw new IllegalStateException("Invalid Authentication " + realm);
205-
}
206-
}
207-
208-
return proxyAuthorization;
209-
}
210-
21193
private NettyBody body(Request request, boolean connect) throws IOException {
21294
NettyBody nettyBody = null;
21395
if (!connect) {
@@ -340,9 +222,9 @@ public NettyRequest newNettyRequest(Request request, Uri uri, boolean forceConne
340222
Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm();
341223

342224
// don't override authorization but append
343-
addAuthorizationHeader(headers, systematicAuthorizationHeader(request, uri, realm));
225+
addAuthorizationHeader(headers, perRequestAuthorizationHeader(request, uri, realm));
344226

345-
setProxyAuthorizationHeader(headers, systematicProxyAuthorizationHeader(request, realm, proxyServer, connect));
227+
setProxyAuthorizationHeader(headers, perRequestProxyAuthorizationHeader(request, realm, proxyServer, connect));
346228

347229
// Add default accept headers
348230
if (!headers.contains(HttpHeaders.Names.ACCEPT))

src/main/java/com/ning/http/client/providers/netty/request/NettyRequestSender.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import static com.ning.http.util.AsyncHttpProviderUtils.REMOTELY_CLOSED_EXCEPTION;
1919
import static com.ning.http.util.AsyncHttpProviderUtils.getDefaultPort;
2020
import static com.ning.http.util.AsyncHttpProviderUtils.requestTimeout;
21+
import static com.ning.http.util.AuthenticatorUtils.perConnectionAuthorizationHeader;
22+
import static com.ning.http.util.AuthenticatorUtils.perConnectionProxyAuthorizationHeader;
2123
import static com.ning.http.util.ProxyUtils.avoidProxy;
2224
import static com.ning.http.util.ProxyUtils.getProxyServer;
2325

@@ -257,8 +259,8 @@ private <T> ListenableFuture<T> sendRequestWithNewChannel(//
257259
HttpHeaders headers = future.getNettyRequest().getHttpRequest().headers();
258260
Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm();
259261
boolean connect = future.getNettyRequest().getHttpRequest().getMethod() == HttpMethod.CONNECT;
260-
requestFactory.addAuthorizationHeader(headers, requestFactory.firstRequestOnlyAuthorizationHeader(request, uri, proxy, realm));
261-
requestFactory.setProxyAuthorizationHeader(headers, requestFactory.firstRequestOnlyProxyAuthorizationHeader(request, proxy, connect));
262+
requestFactory.addAuthorizationHeader(headers, perConnectionAuthorizationHeader(request, uri, proxy, realm));
263+
requestFactory.setProxyAuthorizationHeader(headers, perConnectionProxyAuthorizationHeader(request, proxy, connect));
262264

263265
// Do not throw an exception when we need an extra connection for a
264266
// redirect

src/main/java/com/ning/http/client/providers/netty/spnego/SpnegoEngine.java renamed to src/main/java/com/ning/http/client/spnego/SpnegoEngine.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved.
2+
* Copyright (c) 2010-2015 Sonatype, Inc. All rights reserved.
33
*
44
* This program is licensed to you under the Apache License Version 2.0,
55
* and you may not use this file except in compliance with the Apache License Version 2.0.
@@ -35,7 +35,7 @@
3535
* <http://www.apache.org/>.
3636
*/
3737

38-
package com.ning.http.client.providers.netty.spnego;
38+
package com.ning.http.client.spnego;
3939

4040
import org.ietf.jgss.GSSContext;
4141
import org.ietf.jgss.GSSException;

src/main/java/com/ning/http/client/providers/netty/spnego/SpnegoTokenGenerator.java renamed to src/main/java/com/ning/http/client/spnego/SpnegoTokenGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved.
2+
* Copyright (c) 2010-2015 Sonatype, Inc. All rights reserved.
33
*
44
* This program is licensed to you under the Apache License Version 2.0,
55
* and you may not use this file except in compliance with the Apache License Version 2.0.
@@ -36,7 +36,7 @@
3636
*
3737
*/
3838

39-
package com.ning.http.client.providers.netty.spnego;
39+
package com.ning.http.client.spnego;
4040

4141
import java.io.IOException;
4242

0 commit comments

Comments
 (0)