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