src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
branchJDK-8229867-branch
changeset 57968 8595871a5446
parent 57956 e0b8b019d2f5
equal deleted inserted replaced
57966:e89c7aaf2906 57968:8595871a5446
    28 import java.net.URL;
    28 import java.net.URL;
    29 import java.io.IOException;
    29 import java.io.IOException;
    30 import java.net.Authenticator.RequestorType;
    30 import java.net.Authenticator.RequestorType;
    31 import java.util.Base64;
    31 import java.util.Base64;
    32 import java.util.HashMap;
    32 import java.util.HashMap;
       
    33 import java.util.concurrent.locks.ReentrantLock;
       
    34 
    33 import sun.net.www.HeaderParser;
    35 import sun.net.www.HeaderParser;
    34 import sun.util.logging.PlatformLogger;
    36 import sun.util.logging.PlatformLogger;
    35 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
    37 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
    36 import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
    38 import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
    37 import sun.security.action.GetPropertyAction;
    39 import sun.security.action.GetPropertyAction;
    56     // <code>supported</code> is set when isSupported is checked,
    58     // <code>supported</code> is set when isSupported is checked,
    57     // if it's true, a cached Negotiator is put into <code>cache</code>.
    59     // if it's true, a cached Negotiator is put into <code>cache</code>.
    58     // the cache can be used only once, so after the first use, it's cleaned.
    60     // the cache can be used only once, so after the first use, it's cleaned.
    59     static HashMap <String, Boolean> supported = null;
    61     static HashMap <String, Boolean> supported = null;
    60     static ThreadLocal <HashMap <String, Negotiator>> cache = null;
    62     static ThreadLocal <HashMap <String, Negotiator>> cache = null;
       
    63     private static final ReentrantLock negotiateLock = new ReentrantLock();
       
    64 
    61     /* Whether cache is enabled for Negotiate/Kerberos */
    65     /* Whether cache is enabled for Negotiate/Kerberos */
    62     private static final boolean cacheSPNEGO;
    66     private static final boolean cacheSPNEGO;
    63     static {
    67     static {
    64         String spnegoCacheProp =
    68         String spnegoCacheProp =
    65             GetPropertyAction.privilegedGetProperty("jdk.spnego.cache", "true");
    69             GetPropertyAction.privilegedGetProperty("jdk.spnego.cache", "true");
   124      * If this method is called for the second time on an HttpCallerInfo with
   128      * If this method is called for the second time on an HttpCallerInfo with
   125      * the same hostname, the answer is retrieved from cache.
   129      * the same hostname, the answer is retrieved from cache.
   126      *
   130      *
   127      * @return true if supported
   131      * @return true if supported
   128      */
   132      */
   129     private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) {
   133     private static boolean isSupportedImpl(HttpCallerInfo hci) {
   130         if (supported == null) {
   134         negotiateLock.lock();
   131             supported = new HashMap<>();
   135         try {
   132         }
   136             if (supported == null) {
   133         String hostname = hci.host;
   137                 supported = new HashMap<>();
   134         hostname = hostname.toLowerCase();
   138             }
   135         if (supported.containsKey(hostname)) {
   139             String hostname = hci.host;
   136             return supported.get(hostname);
   140             hostname = hostname.toLowerCase();
   137         }
   141             if (supported.containsKey(hostname)) {
   138 
   142                 return supported.get(hostname);
   139         Negotiator neg = Negotiator.getNegotiator(hci);
   143             }
   140         if (neg != null) {
   144 
   141             supported.put(hostname, true);
   145             Negotiator neg = Negotiator.getNegotiator(hci);
   142             // the only place cache.put is called. here we can make sure
   146             if (neg != null) {
   143             // the object is valid and the oneToken inside is not null
   147                 supported.put(hostname, true);
   144             if (cache == null) {
   148                 // the only place cache.put is called. here we can make sure
   145                 cache = new ThreadLocal<>() {
   149                 // the object is valid and the oneToken inside is not null
   146                     @Override
   150                 if (cache == null) {
   147                     protected HashMap<String, Negotiator> initialValue() {
   151                     cache = new ThreadLocal<>() {
   148                         return new HashMap<>();
   152                         @Override
   149                     }
   153                         protected HashMap<String, Negotiator> initialValue() {
   150                 };
   154                             return new HashMap<>();
   151             }
   155                         }
   152             cache.get().put(hostname, neg);
   156                     };
   153             return true;
   157                 }
   154         } else {
   158                 cache.get().put(hostname, neg);
   155             supported.put(hostname, false);
   159                 return true;
   156             return false;
   160             } else {
   157         }
   161                 supported.put(hostname, false);
   158     }
   162                 return false;
   159 
   163             }
   160     private static synchronized HashMap<String, Negotiator> getCache() {
   164         } finally {
   161         if (cache == null) return null;
   165             negotiateLock.unlock();
   162         return cache.get();
   166         }
       
   167     }
       
   168 
       
   169     private static HashMap<String, Negotiator> getCache() {
       
   170         negotiateLock.lock();
       
   171         try {
       
   172             if (cache == null) return null;
       
   173             return cache.get();
       
   174         } finally {
       
   175             negotiateLock.unlock();
       
   176         }
   163     }
   177     }
   164 
   178 
   165     @Override
   179     @Override
   166     protected boolean useAuthCache() {
   180     protected boolean useAuthCache() {
   167         return super.useAuthCache() && cacheSPNEGO;
   181         return super.useAuthCache() && cacheSPNEGO;
   195      *          HeaderParser converts the fields to lower case, use raw instead
   209      *          HeaderParser converts the fields to lower case, use raw instead
   196      * @param raw The raw header field.
   210      * @param raw The raw header field.
   197      * @return true if all goes well, false if no headers were set.
   211      * @return true if all goes well, false if no headers were set.
   198      */
   212      */
   199     @Override
   213     @Override
   200     public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
   214     public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
   201 
   215 
   202         try {
   216         try {
   203             String response;
   217             String response;
   204             byte[] incoming = null;
   218             byte[] incoming = null;
   205             String[] parts = raw.split("\\s+");
   219             String[] parts = raw.split("\\s+");