1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.talika.tarsis.filters.security;
24
25 import java.io.IOException;
26
27 import javax.servlet.FilterChain;
28 import javax.servlet.FilterConfig;
29 import javax.servlet.ServletException;
30 import javax.servlet.ServletRequest;
31 import javax.servlet.ServletResponse;
32 import javax.servlet.UnavailableException;
33 import javax.servlet.http.HttpServletRequest;
34
35 import org.talika.tarsis.Globals;
36 import org.talika.tarsis.command.Command;
37 import org.talika.tarsis.filters.CommandFilter;
38 import org.talika.tarsis.security.AuthenticationFailedException;
39 import org.talika.tarsis.security.AuthenticationRequiredException;
40 import org.talika.tarsis.security.Authenticator;
41 import org.talika.tarsis.security.Authorizator;
42 import org.talika.tarsis.security.SecuritySession;
43 import org.talika.tarsis.security.SecuritySessionManager;
44
45 /**
46 * Login filter checks if client's request has a valid security session and if not
47 * tries to authenticate client.
48 *
49 * @author Jose M. Palomar
50 * @version $Revision: 269 $
51 */
52 public final class LoginFilter extends CommandFilter {
53
54
55 /**
56 * Login page parameter name.
57 */
58 public static final String LOGIN_PAGE_PARAM = "loginPage";
59
60 /**
61 * Number login of tries parameter name.
62 */
63 public static final String LOGIN_TRIES_PARAM = "loginTries";
64
65 /**
66 * Default number login of tries.
67 */
68 private static final int DEFAULT_LOGIN_TRIES = 3;
69
70
71 /**
72 * Login page.
73 */
74 private String loginPage;
75
76 /**
77 * Login tries.
78 */
79 private int loginTries;
80
81 /**
82 * Tarsis authenticator.
83 */
84 private Authenticator authenticator;
85
86 /**
87 * Tarsis authorizator.
88 */
89 private Authorizator authorizator;
90
91 /**
92 * Tarsis session manager.
93 */
94 private SecuritySessionManager securitySessionManager;
95
96
97 /**
98 * Called by the web container to indicate to a filter that it is being placed
99 * into service.<br>
100 * <br>
101 * Initialization consits in:
102 * <ol>
103 * <li>Calling super <code>int</code> method.</li>
104 * <li>Retrieves login page parameter.</li>
105 * <li>Retrieves login tries parameter.</li>
106 * <li>Stores in a local variable authenticator instance.</li>
107 * <li>Stores in a local variable authorizator instance.</li>
108 * <li>Stores in a local variable security session manager instance.</li>
109 * </ol>
110 *
111 * @param filterConfig FilterConfig filter configutarion.
112 * @throws ServletException if an exception has occurred that interferes with the
113 * filter's normal operation
114 * @see javax.servlet.Filter#init(FilterConfig)
115 */
116 public void init(FilterConfig filterConfig) throws ServletException {
117 super.init(filterConfig);
118
119 this.loginPage = filterConfig.getInitParameter(LOGIN_PAGE_PARAM);
120 if (this.loginPage == null) {
121 throw new UnavailableException("Invalid loginPage value");
122 }
123
124 String loginTriesStr = filterConfig.getInitParameter(LOGIN_TRIES_PARAM);
125 if (loginTriesStr != null) {
126
127 try {
128 this.loginTries = Integer.parseInt(loginTriesStr);
129 }
130 catch (NumberFormatException nfe) {
131 this.loginTries = DEFAULT_LOGIN_TRIES;
132 }
133
134 }
135 else {
136 this.loginTries = DEFAULT_LOGIN_TRIES;
137 }
138
139 this.securitySessionManager = SecuritySessionManager.getInstance();
140 this.authenticator = getContext().getAuthenticator();
141 this.authorizator = getContext().getAuthorizator();
142
143 }
144
145 /**
146 * Checks if client's request has a valid security session and if not tries to
147 * authenticate client.<br>
148 * <br>
149 * Filter checks if command is restricted, then checks if there is a valid
150 * security session, if there is continue with next filter in chain.<br>
151 * If not saves current request for later resume and forwards to login page. In
152 * next invocation obtains username and password from login request and tries to
153 * authenticate client with them. Repeats proccess number of times in login tries.
154 * If authentication is valid resumes saved request.
155 *
156 * @param request ServletRequest the <code>ServletRequest</code> object
157 * that contains the client's request.
158 * @param response ServletResponse the <code>ServletResponse</code> object
159 * that contains the servlet's response.
160 * @param chain FilterChain invocation chain of filtered request.
161 * @throws IOException if an input or output exception occurs
162 * @throws ServletException if an exception has occurred that interferes with the
163 * filter's normal operation
164 * @see javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
165 */
166 public void doFilter(ServletRequest request, ServletResponse response,
167 FilterChain chain)
168 throws IOException, ServletException {
169
170 if (getLogger().isDebugEnabled()) {
171 getLogger().logDebug(getFilterConfig().getFilterName() + ": invoked");
172 }
173
174 try {
175
176
177 Command cmd = findCommand(request);
178
179
180 LoginSession loginSession = getLoginSession((HttpServletRequest) request);
181
182
183 String username = request.getParameter(Globals.USERNAME_PARAMETER);
184 String password = request.getParameter(Globals.PASSWORD_PARAMETER);
185
186
187 if (((cmd != null) && authorizator.isRestricted(cmd)) ||
188 ((username != null) || (password != null))) {
189
190
191 if (!securitySessionManager.isSecuritySessionValid((HttpServletRequest) request)) {
192
193 try {
194
195 processLogin((HttpServletRequest) request, username, password);
196
197 }
198 catch (AuthenticationFailedException afe) {
199
200 loginSession.incTries();
201 if (loginSession.getTries() > this.loginTries) {
202 throw new AuthenticationRequiredException();
203 }
204 else {
205 request.getRequestDispatcher(this.loginPage).forward(request, response);
206 return;
207 }
208
209 }
210
211
212 chain.doFilter(new LoginRequestWrapper((HttpServletRequest) request,
213 loginSession.getParameters(),
214 loginSession.getAttributes()),
215 response);
216
217 }
218
219 }
220 else {
221 chain.doFilter(request, response);
222 }
223
224 }
225 catch (ServletException se) {
226 throw se;
227 }
228 catch (Throwable t) {
229 throw new ServletException(t);
230 }
231
232 }
233
234 /**
235 * Tries to log client using username and password. If authentication is correct
236 * creates a new <code>SecuritySession</code> and stores it in client's
237 * <code>HttpSession</code>.
238 *
239 * @param request HttpServletRequest client's request.
240 * @param username String user name.
241 * @param password String user password.
242 * @throws AuthenticationFailedException if can't authenticate user using given
243 * username and passowrd.
244 */
245 protected void processLogin(HttpServletRequest request, String username, String password)
246 throws AuthenticationFailedException {
247
248 if ((username != null) && (password != null)) {
249
250 SecuritySession securitySession =
251 authenticator.login(username, password);
252
253 securitySessionManager.saveSecuritySession(request, securitySession);
254
255 removeLoginSession(request);
256
257 }
258 else {
259 throw new AuthenticationFailedException();
260 }
261
262 }
263
264 /**
265 * Retrieves <code>LoginSession</code> from client's request.
266 *
267 * @param request HttpServletRequest client's request.
268 * @return LoginSession session obtained or <code>null</code>.
269 */
270 private LoginSession getLoginSession(HttpServletRequest request) {
271 LoginSession loginSession = (LoginSession) request.getSession().getAttribute(Globals.LOGIN_SESSION_ATTR);
272 if (loginSession == null) {
273 loginSession = new LoginSession(request);
274 request.getSession().setAttribute(Globals.LOGIN_SESSION_ATTR, loginSession);
275 }
276 return loginSession;
277 }
278
279 /**
280 * Removes <code>LoginSession</code> from client's request.
281 *
282 * @param request HttpServletRequest client's request.
283 */
284 private void removeLoginSession(HttpServletRequest request) {
285 request.removeAttribute(Globals.LOGIN_SESSION_ATTR);
286 }
287
288 }