1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.apache.commons.httpclient.auth;
32
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.List;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40 /***
41 * Authentication policy class. The Authentication policy provides corresponding
42 * authentication scheme interfrace for a given type of authorization challenge.
43 * <p>The following specifications are provided:
44 * <ul>
45 * <li><tt>Basic</tt>: Basic authentication scheme as defined in RFC2617
46 * (considered inherently insecure, but most widely supported)
47 * <li><tt>Digest</tt>: Digest authentication scheme as defined in RFC2617
48 * <li><tt>NTLM</tt>: The NTLM scheme is a proprietary Microsoft Windows
49 * Authentication protocol (considered to be the most secure among
50 * currently supported authentication schemes)
51 * </ul>
52 *
53 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
54 *
55 * @version $Revision$
56 * @since 3.0
57 */
58 public abstract class AuthPolicy {
59
60 private static final HashMap SCHEMES = new HashMap();
61 private static final ArrayList SCHEME_LIST = new ArrayList();
62
63 /***
64 * The key used to look up the list of IDs of supported {@link AuthScheme
65 * authentication schemes} in their order of preference. The scheme IDs are
66 * stored in a {@link java.util.Collection} as {@link java.lang.String}s.
67 *
68 * <p>
69 * If several schemes are returned in the <tt>WWW-Authenticate</tt>
70 * or <tt>Proxy-Authenticate</tt> header, this parameter defines which
71 * {@link AuthScheme authentication schemes} takes precedence over others.
72 * The first item in the collection represents the most preferred
73 * {@link AuthScheme authentication scheme}, the last item represents the ID
74 * of the least preferred one.
75 * </p>
76 *
77 * @see org.apache.commons.httpclient.params.DefaultHttpParams
78 */
79 public static final String AUTH_SCHEME_PRIORITY = "http.auth.scheme-priority";
80
81 /***
82 * The NTLM scheme is a proprietary Microsoft Windows Authentication
83 * protocol (considered to be the most secure among currently supported
84 * authentication schemes).
85 */
86 public static final String NTLM = "NTLM";
87
88 /***
89 * Digest authentication scheme as defined in RFC2617.
90 */
91 public static final String DIGEST = "Digest";
92
93 /***
94 * Basic authentication scheme as defined in RFC2617 (considered inherently
95 * insecure, but most widely supported)
96 */
97 public static final String BASIC = "Basic";
98
99 static {
100 AuthPolicy.registerAuthScheme(NTLM, NTLMScheme.class);
101 AuthPolicy.registerAuthScheme(DIGEST, DigestScheme.class);
102 AuthPolicy.registerAuthScheme(BASIC, BasicScheme.class);
103 }
104
105 /*** Log object. */
106 protected static final Log LOG = LogFactory.getLog(AuthPolicy.class);
107
108 /***
109 * Registers a class implementing an {@link AuthScheme authentication scheme} with
110 * the given identifier. If a class with the given ID already exists it will be overridden.
111 * This ID is the same one used to retrieve the {@link AuthScheme authentication scheme}
112 * from {@link #getAuthScheme(String)}.
113 *
114 * <p>
115 * Please note that custom authentication preferences, if used, need to be updated accordingly
116 * for the new {@link AuthScheme authentication scheme} to take effect.
117 * </p>
118 *
119 * @param id the identifier for this scheme
120 * @param clazz the class to register
121 *
122 * @see #getAuthScheme(String)
123 * @see #AUTH_SCHEME_PRIORITY
124 */
125 public static synchronized void registerAuthScheme(final String id, Class clazz) {
126 if (id == null) {
127 throw new IllegalArgumentException("Id may not be null");
128 }
129 if (clazz == null) {
130 throw new IllegalArgumentException("Authentication scheme class may not be null");
131 }
132 SCHEMES.put(id.toLowerCase(), clazz);
133 SCHEME_LIST.add(id.toLowerCase());
134 }
135
136 /***
137 * Unregisters the class implementing an {@link AuthScheme authentication scheme} with
138 * the given ID.
139 *
140 * @param id the ID of the class to unregister
141 */
142 public static synchronized void unregisterAuthScheme(final String id) {
143 if (id == null) {
144 throw new IllegalArgumentException("Id may not be null");
145 }
146 SCHEMES.remove(id.toLowerCase());
147 SCHEME_LIST.remove(id.toLowerCase());
148 }
149
150 /***
151 * Gets the {@link AuthScheme authentication scheme} with the given ID.
152 *
153 * @param id the {@link AuthScheme authentication scheme} ID
154 *
155 * @return {@link AuthScheme authentication scheme}
156 *
157 * @throws IllegalStateException if a scheme with the ID cannot be found
158 */
159 public static synchronized AuthScheme getAuthScheme(final String id)
160 throws IllegalStateException {
161
162 if (id == null) {
163 throw new IllegalArgumentException("Id may not be null");
164 }
165 Class clazz = (Class)SCHEMES.get(id.toLowerCase());
166 if (clazz != null) {
167 try {
168 return (AuthScheme)clazz.newInstance();
169 } catch (Exception e) {
170 LOG.error("Error initializing authentication scheme: " + id, e);
171 throw new IllegalStateException(id +
172 " authentication scheme implemented by " +
173 clazz.getName() + " could not be initialized");
174 }
175 } else {
176 throw new IllegalStateException("Unsupported authentication scheme " + id);
177 }
178 }
179
180 /***
181 * Returns a list containing all registered {@link AuthScheme authentication
182 * schemes} in their default order.
183 *
184 * @return {@link AuthScheme authentication scheme}
185 */
186 public static synchronized List getDefaultAuthPrefs() {
187 return (List)SCHEME_LIST.clone();
188 }
189 }