1/* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/AbstractAuthenticationHandler.java $ 3 * $Revision: 673450 $ 4 * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $ 5 * 6 * ==================================================================== 7 * Licensed to the Apache Software Foundation (ASF) under one 8 * or more contributor license agreements. See the NOTICE file 9 * distributed with this work for additional information 10 * regarding copyright ownership. The ASF licenses this file 11 * to you under the Apache License, Version 2.0 (the 12 * "License"); you may not use this file except in compliance 13 * with the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, 18 * software distributed under the License is distributed on an 19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20 * KIND, either express or implied. See the License for the 21 * specific language governing permissions and limitations 22 * under the License. 23 * ==================================================================== 24 * 25 * This software consists of voluntary contributions made by many 26 * individuals on behalf of the Apache Software Foundation. For more 27 * information on the Apache Software Foundation, please see 28 * <http://www.apache.org/>. 29 * 30 */ 31 32package org.apache.http.impl.client; 33 34import java.util.Arrays; 35import java.util.HashMap; 36import java.util.List; 37import java.util.Locale; 38import java.util.Map; 39 40import org.apache.commons.logging.Log; 41import org.apache.commons.logging.LogFactory; 42import org.apache.http.FormattedHeader; 43import org.apache.http.Header; 44import org.apache.http.HttpResponse; 45import org.apache.http.auth.AuthScheme; 46import org.apache.http.auth.AuthSchemeRegistry; 47import org.apache.http.auth.AuthenticationException; 48import org.apache.http.auth.MalformedChallengeException; 49import org.apache.http.client.AuthenticationHandler; 50import org.apache.http.client.protocol.ClientContext; 51import org.apache.http.protocol.HTTP; 52import org.apache.http.protocol.HttpContext; 53import org.apache.http.util.CharArrayBuffer; 54 55/** 56 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> 57 */ 58public abstract class AbstractAuthenticationHandler implements AuthenticationHandler { 59 60 private final Log log = LogFactory.getLog(getClass()); 61 62 private static final List<String> DEFAULT_SCHEME_PRIORITY = Arrays.asList(new String[] { 63 "ntlm", 64 "digest", 65 "basic" 66 }); 67 68 public AbstractAuthenticationHandler() { 69 super(); 70 } 71 72 protected Map<String, Header> parseChallenges( 73 final Header[] headers) throws MalformedChallengeException { 74 75 Map<String, Header> map = new HashMap<String, Header>(headers.length); 76 for (Header header : headers) { 77 CharArrayBuffer buffer; 78 int pos; 79 if (header instanceof FormattedHeader) { 80 buffer = ((FormattedHeader) header).getBuffer(); 81 pos = ((FormattedHeader) header).getValuePos(); 82 } else { 83 String s = header.getValue(); 84 if (s == null) { 85 throw new MalformedChallengeException("Header value is null"); 86 } 87 buffer = new CharArrayBuffer(s.length()); 88 buffer.append(s); 89 pos = 0; 90 } 91 while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) { 92 pos++; 93 } 94 int beginIndex = pos; 95 while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) { 96 pos++; 97 } 98 int endIndex = pos; 99 String s = buffer.substring(beginIndex, endIndex); 100 map.put(s.toLowerCase(Locale.ENGLISH), header); 101 } 102 return map; 103 } 104 105 protected List<String> getAuthPreferences() { 106 return DEFAULT_SCHEME_PRIORITY; 107 } 108 109 public AuthScheme selectScheme( 110 final Map<String, Header> challenges, 111 final HttpResponse response, 112 final HttpContext context) throws AuthenticationException { 113 114 AuthSchemeRegistry registry = (AuthSchemeRegistry) context.getAttribute( 115 ClientContext.AUTHSCHEME_REGISTRY); 116 if (registry == null) { 117 throw new IllegalStateException("AuthScheme registry not set in HTTP context"); 118 } 119 120 List<?> authPrefs = (List<?>) context.getAttribute( 121 ClientContext.AUTH_SCHEME_PREF); 122 if (authPrefs == null) { 123 authPrefs = getAuthPreferences(); 124 } 125 126 if (this.log.isDebugEnabled()) { 127 this.log.debug("Authentication schemes in the order of preference: " 128 + authPrefs); 129 } 130 131 AuthScheme authScheme = null; 132 for (int i = 0; i < authPrefs.size(); i++) { 133 String id = (String) authPrefs.get(i); 134 Header challenge = challenges.get(id.toLowerCase(Locale.ENGLISH)); 135 136 if (challenge != null) { 137 if (this.log.isDebugEnabled()) { 138 this.log.debug(id + " authentication scheme selected"); 139 } 140 try { 141 authScheme = registry.getAuthScheme(id, response.getParams()); 142 break; 143 } catch (IllegalStateException e) { 144 if (this.log.isWarnEnabled()) { 145 this.log.warn("Authentication scheme " + id + " not supported"); 146 // Try again 147 } 148 } 149 } else { 150 if (this.log.isDebugEnabled()) { 151 this.log.debug("Challenge for " + id + " authentication scheme not available"); 152 // Try again 153 } 154 } 155 } 156 if (authScheme == null) { 157 // If none selected, something is wrong 158 throw new AuthenticationException( 159 "Unable to respond to any of these challenges: " 160 + challenges); 161 } 162 return authScheme; 163 } 164 165} 166