From d6f9877ef91dd5b1cacee7871cbb70fd40607a2e Mon Sep 17 00:00:00 2001 From: aefimov Date: Tue, 17 Jan 2017 15:35:57 +0300 Subject: [PATCH] 8170814: Reuse cache entries (part II) Reviewed-by: dfuchs --- .../classes/sun/net/www/http/HttpClient.java | 27 +++++++++-- .../http/NegotiateAuthentication.java | 47 ++++++++++++++----- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/src/share/classes/sun/net/www/http/HttpClient.java b/src/share/classes/sun/net/www/http/HttpClient.java index da59473fb..d0f2e9387 100644 --- a/src/share/classes/sun/net/www/http/HttpClient.java +++ b/src/share/classes/sun/net/www/http/HttpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,6 +102,11 @@ public class HttpClient extends NetworkClient { if false, then NTLM connections will not be cached. The default value is 'true'. */ private static final boolean cacheNTLMProp; + /* Value of the system property jdk.spnego.cache; + if false, then connections authentified using the Negotiate/Kerberos + scheme will not be cached. + The default value is 'true'. */ + private static final boolean cacheSPNEGOProp; volatile boolean keepingAlive = false; /* this is a keep-alive connection */ volatile boolean disableKeepAlive;/* keep-alive has been disabled for this @@ -160,6 +165,9 @@ public class HttpClient extends NetworkClient { String cacheNTLM = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("jdk.ntlm.cache")); + String cacheSPNEGO = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("jdk.spnego.cache")); + if (keepAlive != null) { keepAliveProp = Boolean.valueOf(keepAlive).booleanValue(); } else { @@ -177,6 +185,12 @@ public class HttpClient extends NetworkClient { } else { cacheNTLMProp = true; } + + if (cacheSPNEGO != null) { + cacheSPNEGOProp = Boolean.parseBoolean(cacheSPNEGO); + } else { + cacheSPNEGOProp = true; + } } /** @@ -770,9 +784,16 @@ public class HttpClient extends NetworkClient { // and cacheNTLMProp is false, than we can't keep this connection // alive: we will switch disableKeepAlive to true. boolean canKeepAlive = !disableKeepAlive; - if (canKeepAlive && cacheNTLMProp == false && authenticate != null) { + if (canKeepAlive && (cacheNTLMProp == false || cacheSPNEGOProp == false) + && authenticate != null) { authenticate = authenticate.toLowerCase(Locale.US); - canKeepAlive = !authenticate.startsWith("ntlm "); + if (cacheNTLMProp == false) { + canKeepAlive &= !authenticate.startsWith("ntlm "); + } + if (cacheSPNEGOProp == false) { + canKeepAlive &= !authenticate.startsWith("negotiate "); + canKeepAlive &= !authenticate.startsWith("kerberos "); + } } disableKeepAlive |= !canKeepAlive; diff --git a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java index 9e2a49a03..0b42768f5 100644 --- a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java +++ b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import sun.net.www.HeaderParser; import sun.util.logging.PlatformLogger; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; +import sun.security.action.GetPropertyAction; /** * NegotiateAuthentication: @@ -52,10 +53,18 @@ class NegotiateAuthentication extends AuthenticationInfo { // These maps are used to manage the GSS availability for diffrent // hosts. The key for both maps is the host name. // supported is set when isSupported is checked, + // if it's true, a cached Negotiator is put into cache. // the cache can be used only once, so after the first use, it's cleaned. static HashMap supported = null; - static HashMap cache = null; + static ThreadLocal > cache = null; + /* Whether cache is enabled for Negotiate/Kerberos */ + private static final boolean cacheSPNEGO; + static { + String spnegoCacheProp = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("jdk.spnego.cache", "true")); + cacheSPNEGO = Boolean.parseBoolean(spnegoCacheProp); + } // The HTTP Negotiate Helper private Negotiator negotiator = null; @@ -118,8 +127,7 @@ class NegotiateAuthentication extends AuthenticationInfo { */ private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) { if (supported == null) { - supported = new HashMap (); - cache = new HashMap (); + supported = new HashMap<>(); } String hostname = hci.host; hostname = hostname.toLowerCase(); @@ -132,7 +140,15 @@ class NegotiateAuthentication extends AuthenticationInfo { supported.put(hostname, true); // the only place cache.put is called. here we can make sure // the object is valid and the oneToken inside is not null - cache.put(hostname, neg); + if (cache == null) { + cache = new ThreadLocal>() { + @Override + protected HashMap initialValue() { + return new HashMap<>(); + } + }; + } + cache.get().put(hostname, neg); return true; } else { supported.put(hostname, false); @@ -140,6 +156,16 @@ class NegotiateAuthentication extends AuthenticationInfo { } } + private static synchronized HashMap getCache() { + if (cache == null) return null; + return cache.get(); + } + + @Override + protected boolean useAuthCache() { + return super.useAuthCache() && cacheSPNEGO; + } + /** * Not supported. Must use the setHeaders() method */ @@ -197,12 +223,11 @@ class NegotiateAuthentication extends AuthenticationInfo { */ private byte[] firstToken() throws IOException { negotiator = null; - if (cache != null) { - synchronized(cache) { - negotiator = cache.get(getHost()); - if (negotiator != null) { - cache.remove(getHost()); // so that it is only used once - } + HashMap cachedMap = getCache(); + if (cachedMap != null) { + negotiator = cachedMap.get(getHost()); + if (negotiator != null) { + cachedMap.remove(getHost()); // so that it is only used once } } if (negotiator == null) { -- GitLab