1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.ui.webapp;
17
18 import org.acegisecurity.Authentication;
19 import org.acegisecurity.AuthenticationException;
20
21 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
22
23 import org.acegisecurity.ui.WebAuthenticationDetails;
24
25 import javax.servlet.FilterConfig;
26 import javax.servlet.ServletException;
27 import javax.servlet.http.HttpServletRequest;
28
29
30 /***
31 * Extends Acegi's AuthenticationProcessingFilter to pick up Netegrity
32 * Siteminder's headers.
33 *
34 * <P>
35 * Also provides a backup form-based authentication and the ability set source
36 * key names.
37 * </p>
38 *
39 * <P>
40 * <B>Siteminder</B> must present two <B>headers</B> to this filter, a username
41 * and password. You must set the header keys before this filter is used for
42 * authentication, otherwise Siteminder checks will be skipped. If the
43 * Siteminder check is unsuccessful (i.e. if the headers are not found), then
44 * the form parameters will be checked (see next paragraph). This allows
45 * applications to optionally function even when their Siteminder
46 * infrastructure is unavailable, as is often the case during development.
47 * </p>
48 *
49 * <P>
50 * <B>Login forms</B> must present two <B>parameters</B> to this filter: a
51 * username and password. If not specified, the parameter names to use are
52 * contained in the static fields {@link #ACEGI_SECURITY_FORM_USERNAME_KEY}
53 * and {@link #ACEGI_SECURITY_FORM_PASSWORD_KEY}.
54 * </p>
55 *
56 * <P>
57 * <B>Do not use this class directly.</B> Instead, configure
58 * <code>web.xml</code> to use the {@link
59 * org.acegisecurity.util.FilterToBeanProxy}.
60 * </p>
61 */
62 public class SiteminderAuthenticationProcessingFilter
63 extends AuthenticationProcessingFilter {
64
65
66 /*** Form password request key. */
67 private String formPasswordParameterKey = null;
68
69 /*** Form username request key. */
70 private String formUsernameParameterKey = null;
71
72 /*** Siteminder password header key. */
73 private String siteminderPasswordHeaderKey = null;
74
75 /*** Siteminder username header key. */
76 private String siteminderUsernameHeaderKey = null;
77
78
79
80 /***
81 * Basic constructor.
82 */
83 public SiteminderAuthenticationProcessingFilter() {
84 super();
85 }
86
87
88
89 /***
90 * @see org.acegisecurity.ui.AbstractProcessingFilter#attemptAuthentication(javax.servlet.http.HttpServletRequest)
91 */
92 public Authentication attemptAuthentication(HttpServletRequest request)
93 throws AuthenticationException {
94 String username = null;
95 String password = null;
96
97
98 if ((siteminderUsernameHeaderKey != null)
99 && (siteminderUsernameHeaderKey.length() > 0)
100 && (siteminderPasswordHeaderKey != null)
101 && (siteminderPasswordHeaderKey.length() > 0)) {
102 username = request.getHeader(siteminderUsernameHeaderKey);
103 password = request.getHeader(siteminderPasswordHeaderKey);
104 }
105
106
107
108 if ((username == null) || (username.length() == 0)
109 || (password == null) || (password.length() == 0)) {
110 if (logger.isDebugEnabled()) {
111 logger.debug(
112 "Siteminder headers not found for authentication, so trying to use form values");
113 }
114
115 if ((formUsernameParameterKey != null)
116 && (formUsernameParameterKey.length() > 0)) {
117 username = request.getParameter(formUsernameParameterKey);
118 } else {
119 username = request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY);
120 }
121
122 password = obtainPassword(request);
123 }
124
125
126
127
128 if (username != null) {
129 username = username.toUpperCase();
130 } else {
131
132 username = "";
133 }
134
135 if (password != null) {
136 password = password.toUpperCase();
137 } else {
138
139 password = "";
140 }
141
142 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
143 password);
144
145
146 setDetails(request, authRequest);
147
148
149 request.getSession()
150 .setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username);
151
152 return this.getAuthenticationManager().authenticate(authRequest);
153 }
154
155 /***
156 * This filter by default responds to <code>/j_acegi_security_check</code>.
157 *
158 * @return the default
159 */
160 public String getDefaultFilterProcessesUrl() {
161 return "/j_acegi_security_check";
162 }
163
164 /***
165 * Returns the form password parameter key.
166 *
167 * @return The form password parameter key.
168 */
169 public String getFormPasswordParameterKey() {
170 return formPasswordParameterKey;
171 }
172
173 /***
174 * Returns the form username parameter key.
175 *
176 * @return The form username parameter key.
177 */
178 public String getFormUsernameParameterKey() {
179 return formUsernameParameterKey;
180 }
181
182 /***
183 * Returns the Siteminder password header key.
184 *
185 * @return The Siteminder password header key.
186 */
187 public String getSiteminderPasswordHeaderKey() {
188 return siteminderPasswordHeaderKey;
189 }
190
191 /***
192 * Returns the Siteminder username header key.
193 *
194 * @return The Siteminder username header key.
195 */
196 public String getSiteminderUsernameHeaderKey() {
197 return siteminderUsernameHeaderKey;
198 }
199
200 /***
201 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
202 */
203 public void init(FilterConfig filterConfig) throws ServletException {}
204
205 /***
206 * Enables subclasses to override the composition of the password, such as
207 * by including additional values and a separator.
208 *
209 * <p>
210 * This might be used for example if a postcode/zipcode was required in
211 * addition to the password. A delimiter such as a pipe (|) should be used
212 * to separate the password and extended value(s). The
213 * <code>AuthenticationDao</code> will need to generate the expected
214 * password in a corresponding manner.
215 * </p>
216 *
217 * @param request so that request attributes can be retrieved
218 *
219 * @return the password that will be presented in the
220 * <code>Authentication</code> request token to the
221 * <code>AuthenticationManager</code>
222 */
223 protected String obtainPassword(HttpServletRequest request) {
224 if ((formPasswordParameterKey != null)
225 && (formPasswordParameterKey.length() > 0)) {
226 return request.getParameter(formPasswordParameterKey);
227 } else {
228 return request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY);
229 }
230 }
231
232 /***
233 * Provided so that subclasses may configure what is put into the
234 * authentication request's details property. The default implementation
235 * simply constructs {@link WebAuthenticationDetails}.
236 *
237 * @param request that an authentication request is being created for
238 * @param authRequest the authentication request object that should have
239 * its details set
240 */
241 protected void setDetails(HttpServletRequest request,
242 UsernamePasswordAuthenticationToken authRequest) {
243 authRequest.setDetails(new WebAuthenticationDetails(request));
244 }
245
246 /***
247 * Sets the form password parameter key.
248 *
249 * @param key The form password parameter key.
250 */
251 public void setFormPasswordParameterKey(final String key) {
252 this.formPasswordParameterKey = key;
253 }
254
255 /***
256 * Sets the form username parameter key.
257 *
258 * @param key The form username parameter key.
259 */
260 public void setFormUsernameParameterKey(final String key) {
261 this.formUsernameParameterKey = key;
262 }
263
264 /***
265 * Sets the Siteminder password header key.
266 *
267 * @param key The Siteminder password header key.
268 */
269 public void setSiteminderPasswordHeaderKey(final String key) {
270 this.siteminderPasswordHeaderKey = key;
271 }
272
273 /***
274 * Sets the Siteminder username header key.
275 *
276 * @param key The Siteminder username header key.
277 */
278 public void setSiteminderUsernameHeaderKey(final String key) {
279 this.siteminderUsernameHeaderKey = key;
280 }
281 }