changeset 8680:7ce6f30c4fbd

8170814: Reuse cache entries (part II) Reviewed-by: dfuchs
author aefimov
date Tue, 17 Jan 2017 15:35:57 +0300
parents 815d05b1ba7d
children 797914a333ca
files src/share/classes/sun/net/www/http/HttpClient.java src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
diffstat 2 files changed, 60 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/net/www/http/HttpClient.java	Fri Apr 21 06:33:53 2017 +0100
+++ b/src/share/classes/sun/net/www/http/HttpClient.java	Tue Jan 17 15:35:57 2017 +0300
@@ -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 @@
        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 @@
         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 @@
         } else {
             cacheNTLMProp = true;
         }
+
+        if (cacheSPNEGO != null) {
+            cacheSPNEGOProp = Boolean.parseBoolean(cacheSPNEGO);
+        } else {
+            cacheSPNEGOProp = true;
+        }
     }
 
     /**
@@ -756,9 +770,16 @@
                 // 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;
 
--- a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Fri Apr 21 06:33:53 2017 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Tue Jan 17 15:35:57 2017 +0300
@@ -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
@@ -35,6 +35,7 @@
 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:
@@ -53,10 +54,18 @@
     // These maps are used to manage the GSS availability for diffrent
     // hosts. The key for both maps is the host name.
     // <code>supported</code> is set when isSupported is checked,
+
     // if it's true, a cached Negotiator is put into <code>cache</code>.
     // the cache can be used only once, so after the first use, it's cleaned.
     static HashMap <String, Boolean> supported = null;
-    static HashMap <String, Negotiator> cache = null;
+    static ThreadLocal <HashMap <String, Negotiator>> 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;
@@ -119,8 +128,7 @@
      */
     private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) {
         if (supported == null) {
-            supported = new HashMap <String, Boolean>();
-            cache = new HashMap <String, Negotiator>();
+            supported = new HashMap<>();
         }
         String hostname = hci.host;
         hostname = hostname.toLowerCase();
@@ -133,7 +141,15 @@
             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<HashMap<String, Negotiator>>() {
+                    @Override
+                    protected HashMap<String, Negotiator> initialValue() {
+                        return new HashMap<>();
+                    }
+                };
+            }
+            cache.get().put(hostname, neg);
             return true;
         } else {
             supported.put(hostname, false);
@@ -141,6 +157,16 @@
         }
     }
 
+    private static synchronized HashMap<String, Negotiator> getCache() {
+        if (cache == null) return null;
+        return cache.get();
+    }
+
+    @Override
+    protected boolean useAuthCache() {
+        return super.useAuthCache() && cacheSPNEGO;
+    }
+
     /**
      * Not supported. Must use the setHeaders() method
      */
@@ -198,12 +224,11 @@
      */
     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 <String, Negotiator> 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) {