KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > security > actions > ShowLogonAction


1 package com.sslexplorer.security.actions;
2
3 import java.util.Calendar JavaDoc;
4 import java.util.GregorianCalendar JavaDoc;
5
6 import javax.servlet.http.HttpServletRequest JavaDoc;
7 import javax.servlet.http.HttpServletResponse JavaDoc;
8
9 import org.apache.commons.logging.Log;
10 import org.apache.commons.logging.LogFactory;
11 import org.apache.struts.Globals;
12 import org.apache.struts.action.ActionForm;
13 import org.apache.struts.action.ActionForward;
14 import org.apache.struts.action.ActionMapping;
15 import org.apache.struts.action.ActionMessage;
16 import org.apache.struts.action.ActionMessages;
17
18 import com.sslexplorer.boot.Util;
19 import com.sslexplorer.core.RedirectWithMessages;
20 import com.sslexplorer.core.UserDatabaseManager;
21 import com.sslexplorer.core.actions.DefaultAction;
22 import com.sslexplorer.realms.Realm;
23 import com.sslexplorer.security.AccountLockedException;
24 import com.sslexplorer.security.AuthenticationModule;
25 import com.sslexplorer.security.AuthenticationScheme;
26 import com.sslexplorer.security.Constants;
27 import com.sslexplorer.security.DefaultAuthenticationScheme;
28 import com.sslexplorer.security.LogonController;
29 import com.sslexplorer.security.LogonControllerFactory;
30 import com.sslexplorer.security.LogonStateAndCache;
31 import com.sslexplorer.security.PasswordAuthenticationModule;
32 import com.sslexplorer.security.SecurityErrorException;
33 import com.sslexplorer.security.SessionInfo;
34 import com.sslexplorer.security.SystemDatabaseFactory;
35 import com.sslexplorer.security.User;
36 import com.sslexplorer.security.UserDatabase;
37 import com.sslexplorer.security.UserNotFoundException;
38 import com.sslexplorer.security.forms.LogonForm;
39
40
41 /**
42  * Entry point for authentication process. This action maintains the current
43  * state of the authentication and displays the tiles required for each module.
44  *
45  * @author James Robinson <a HREF="mailto: james@3sp.com">&lt;james@3sp.com&gt;</a>
46  * @author Brett Smith <a HREF="mailto: brett@3sp.com">&lt;brett@3sp.com&gt;</a>
47  */

48 public class ShowLogonAction extends DefaultAction {
49
50     final static Log log = LogFactory.getLog(ShowLogonAction.class);
51
52     /* (non-Javadoc)
53      * @see com.sslexplorer.core.actions.DefaultAction#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
54      */

55     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
56                     throws Exception JavaDoc {
57         LogonForm logonForm = (LogonForm) form;
58         
59         /*
60          * The logon page should not be shown if already logged on. It is
61          * important that hasClientLoggedOn is called first, as this is what
62          * places the session lock in the session attributes.
63          */

64         if (LogonControllerFactory.getInstance().hasClientLoggedOn(request, response) == LogonController.LOGGED_ON
65                         && request.getSession().getAttribute(Constants.SESSION_LOCKED) == null) {
66             return mapping.findForward("home");
67         }
68
69         Util.noCache(response);
70         
71         // Should we reset the logon process
72
boolean reset = request.getParameter("reset") != null;
73         // Or do we need to go back to the start
74
boolean back = request.getParameter("back") != null;
75         
76         // Display any messages that should be displayed
77
displayMessages(request);
78     
79         /*
80          * All other states process as normal
81          */

82         ActionForward fwd;
83         try {
84             
85             if(back) {
86                 /**
87                  * This is designed to take the user back to the start of their default scheme. This
88                  * can only be invoked from the authentication scheme selection page.
89                  */

90                 LogonStateAndCache logonStateMachine = (LogonStateAndCache) request.getSession().getAttribute(
91                         LogonStateAndCache.LOGON_STATE_MACHINE);
92                 logonStateMachine.setState(LogonStateAndCache.STATE_USERNAME_KNOWN);
93                 ((LogonForm) form).setHasMoreAuthenticationSchemes(logonStateMachine.enabledSchemesGraeterThanOne());
94                 return mapping.findForward("display");
95             }
96             
97             // Configure the logon state machine
98
LogonStateAndCache logonStateMachine = checkLogonStateMachine(request, response, logonForm, reset);
99             
100             /*
101              * Only when in STARTED state do we collect the username
102              */

103             if(logonStateMachine.getState() == LogonStateAndCache.STATE_STARTED) {
104                 logonStateMachine.setState(LogonStateAndCache.STATE_DISPLAY_USERNAME_ENTRY);
105                 return mapping.findForward("username");
106             }
107             
108             // try to check the auth session, if not you need to sign in again.
109
fwd = checkAuthSession((LogonForm)form, reset, mapping, request, response, logonStateMachine);
110         } catch (SecurityErrorException see) {
111             ActionMessages errs = new ActionMessages();
112             errs.add(Globals.ERROR_KEY, see.getBundleActionMessage());
113             saveErrors(request, errs);
114             request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
115             if (form != null)
116                 form.reset(mapping, request);
117             return new RedirectWithMessages(mapping.findForward("refresh"), request);
118         } catch (Throwable JavaDoc e) {
119             ActionMessages messages = new ActionMessages();
120             log.error("Logon not allowed.", e);
121             messages.add(Globals.ERROR_KEY, new ActionMessage("login.logonNotAllowed", "Please contact your administrator."));
122             saveErrors(request, messages);
123             request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
124             if (form != null)
125                 form.reset(mapping, request);
126             return new RedirectWithMessages(mapping.findForward("refresh"), request);
127         }
128         Util.noCache(response);
129         return fwd;
130     }
131
132     /**
133      * Check the state of the authentication session and get the next forward
134      * that displays the next authentication module.
135      *
136      * @param form form
137      * @param reset reset authentcation
138      * @param mapping mapping
139      * @param request request
140      * @param response response
141      * @param logonStateMachine logon state machine
142      * @return forward
143      * @throws Exception on any error
144      */

145     public static ActionForward checkAuthSession(LogonForm form, boolean reset, ActionMapping mapping, HttpServletRequest JavaDoc request,
146                     HttpServletResponse JavaDoc response, LogonStateAndCache logonStateMachine) throws Exception JavaDoc{
147         AuthenticationScheme authScheme = (AuthenticationScheme) request.getSession().getAttribute(Constants.AUTH_SESSION);
148         if (authScheme == null || reset || authScheme.getResourceId() != logonStateMachine.getHighestPriorityScheme().getResourceId()) {
149
150             if (log.isDebugEnabled())
151                 log.debug("Creating new authentication session using scheme '" + "THE SCHEME NAME" + "'");
152
153             // Try to initalise the highest priority scheme,
154
if (request.getSession().getAttribute(Constants.SESSION_LOCKED) != null) {
155                 // If session locked then only display password
156

157                 SessionInfo info = LogonControllerFactory.getInstance().getSessionInfo(request);
158                 Calendar JavaDoc now = new GregorianCalendar JavaDoc();
159                 authScheme = new DefaultAuthenticationScheme(info.getRealmId(), Integer.MAX_VALUE, "Fake sheme", "Fake scheme",
160                                 now, now, true, 0);
161                 authScheme.addModule(PasswordAuthenticationModule.MODULE_NAME);
162             } else {
163                 authScheme = logonStateMachine.getHighestPriorityScheme();
164             }
165
166             if (authScheme == null) {
167                 log.info("There are no authenticated schemes.");
168                 return null;
169             } else {
170                 
171                 authScheme.setUser(logonStateMachine.getUser());
172                 authScheme.init(request.getSession());
173                 
174                 if (authScheme.nextAuthenticationModule() == null) {
175                     throw new Exception JavaDoc("No authentication modules have been configured.");
176                 }
177                 request.getSession().setAttribute(Constants.AUTH_SESSION, authScheme);
178                 if (log.isDebugEnabled())
179                     log.debug("Scheme " + authScheme.getSchemeName() + " initialised OK");
180             }
181         }
182
183         while (true) {
184             AuthenticationModule module = authScheme.currentAuthenticationModule();
185             if (form != null) {
186                 form.setCurrentModuleIndex(authScheme.getCurrentModuleIndex());
187             }
188
189             // The module may wish to forward somewhere other than to the
190
// default login page
191
ActionForward forward = module.startAuthentication(mapping, request, response);
192
193             if (module.isRequired()) {
194                 return forward;
195             } else {
196                 // Are we at the end of the sequence
197
if (authScheme.nextAuthenticationModule() == null) {
198                     return LogonAction.finishAuthentication(authScheme, request, response);
199                 }
200             }
201         }
202     }
203     
204     /**
205      * Check the logon state machine and configure as necessary.
206      *
207      * @param request request
208      * @param response response
209      * @param form form
210      * @param reset reset logon
211      * @return logon state machine
212      * @throws Exception on any error
213      */

214     LogonStateAndCache checkLogonStateMachine(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, LogonForm form, boolean reset) throws Exception JavaDoc {
215
216         LogonStateAndCache logonStateMachine = (LogonStateAndCache) request.getSession().getAttribute(
217                         LogonStateAndCache.LOGON_STATE_MACHINE);
218
219         /** Reset the logon state machine if :-
220          *
221          * 1. This is the first connection from this browser session.
222          * 2. The 'reset' parameter has been passed on the request
223          * 3. The logon state machine is in {@link LogonStateAndCache#STATE_RETURN_TO_LOGON}
224          *
225          */

226         UserDatabase udb = UserDatabaseManager.getInstance().getUserDatabase(form.getRealmName());
227         if (logonStateMachine == null || logonStateMachine.getState() == LogonStateAndCache.STATE_RETURN_TO_LOGON || reset) {
228             /*
229              * If the client is already logged on, then we got here because
230              * a <i>Session Lock</i> has occured and so only require
231              * the users password
232              */

233             if (LogonControllerFactory.getInstance().hasClientLoggedOn(request, response) == LogonController.LOGGED_ON) {
234                 logonStateMachine = new LogonStateAndCache(LogonStateAndCache.STATE_DISPLAY_USERNAME_ENTERED, request.getSession());
235                 logonStateMachine.setUser(LogonControllerFactory.getInstance().getUser(request));
236                 form.initUser();
237                 form.setHasMoreAuthenticationSchemes(false);
238             } else {
239                 /*
240                  * This is a brand new session so we require the username
241                  */

242                 logonStateMachine = new LogonStateAndCache(LogonStateAndCache.STATE_STARTED, request.getSession());
243                 request.getSession().removeAttribute(Constants.AUTH_SESSION);
244                 if(!Util.isNullOrTrimmedBlank(form.getUsername())) {
245                     try {
246                         User user = udb.getAccount(form.getUsername());
247                         logonStateMachine.removeFromSpoofCache(user.getPrincipalName());
248                         try {
249                             logonStateMachine.setUser(user);
250                         }
251                         catch(AccountLockedException ale) {
252                             // Continue anyway and get the exception later
253
}
254                         logonStateMachine.setState(LogonStateAndCache.STATE_DISPLAY_USERNAME_ENTERED);
255                     }
256                     catch(UserNotFoundException unfe) {
257                         form.initUser();
258                         // Spoof some authentication schemes
259
form.setHasMoreAuthenticationSchemes(true);
260                     }
261                 }
262                 
263             }
264         } else {
265             /*
266              * A username has been provided but it was unknown. The error message
267              * indicating this will not be displayed until the next stage is
268              * complete
269              */

270             if (logonStateMachine.getState() == LogonStateAndCache.STATE_UNKNOWN_USERNAME) {
271                 logonStateMachine.setState(LogonStateAndCache.STATE_UNKNOWN_USERNAME_PROMPT_FOR_PASSWORD);
272             }
273             else if (logonStateMachine.getState() == LogonStateAndCache.STATE_KNOWN_USERNAME_MULTIPLE_SCHEMES_SELECT){
274                 /*
275                  * The scheme to sign on with has changed, so we need to update the
276                  * logon state machine.
277                  */

278                 logonStateMachine.forceHighestPriorityScheme(request.getParameter("selectedAuthenticationScheme"),
279                         request.getParameter("username"));
280                 logonStateMachine.setState(LogonStateAndCache.STATE_KNOWN_USERNAME_MULTIPLE_SCHEMES);
281             } else if (logonStateMachine.getState() == LogonStateAndCache.STATE_KNOWN_USERNAME_NO_SCHEME_SPOOF_PASSWORD_ENTRY){
282                 /*
283                  * The scheme to sign on with has changed, so we need to update the
284                  * logon state machine
285                  */

286                 logonStateMachine.setSpoofedHighestPriorityScheme(request.getParameter("username"));
287             }
288             else if(logonStateMachine.getState() == LogonStateAndCache.STATE_DISPLAY_USERNAME_ENTRY){
289                 /*
290                  * The username has been collected, now process it.
291                  */

292                 if(Util.isNullOrTrimmedBlank(form.getUsername())) {
293                     /**
294                      * Page refreshed, stay in same state
295                      */

296                     logonStateMachine.setState(LogonStateAndCache.STATE_STARTED);
297                 }
298                 else {
299                     logonStateMachine.setState(LogonStateAndCache.STATE_DISPLAY_USERNAME_ENTERED);
300                     try {
301                         User user = udb.getAccount(form.getUsername());
302                         logonStateMachine.removeFromSpoofCache(user.getPrincipalName());
303                         try {
304                             logonStateMachine.setUser(user);
305                         }
306                         catch(AccountLockedException ale) {
307                             // Continue anyway and get the exception later
308
}
309                     }
310                     catch(UserNotFoundException unfe) {
311                         // Continue anyway
312
String JavaDoc username = request.getParameter("username");
313                         Realm realm = UserDatabaseManager.getInstance().getDefaultRealm();
314                         logonStateMachine.setState(LogonStateAndCache.STATE_UNKNOWN_USERNAME_PROMPT_FOR_PASSWORD);
315                         logonStateMachine.setSpoofedHighestPriorityScheme(username);
316                         logonStateMachine.getHighestPriorityScheme().setAccountLock(LogonControllerFactory.getInstance().checkForAccountLock(username, realm.getResourceName()));
317                     }
318                 }
319             }
320             
321             ((LogonForm) form).setHasMoreAuthenticationSchemes(logonStateMachine.enabledSchemesGraeterThanOne());
322         }
323         
324         return logonStateMachine;
325     }
326     
327     void displayMessages(HttpServletRequest JavaDoc request) throws Exception JavaDoc {
328
329         // Check for session lock and display the message
330

331         if (request.getSession().getAttribute(Constants.SESSION_LOCKED) != null) {
332             ActionMessages messages = new ActionMessages();
333             messages.add(Globals.MESSAGE_KEY, new ActionMessage("login.sessionLocked"));
334             addMessages(request, messages);
335         }
336         
337         // Check Ip address
338

339         if (!SystemDatabaseFactory.getInstance().verifyIPAddress(request.getRemoteAddr())) {
340             ActionMessages errs = new ActionMessages();
341             errs.add(Globals.ERROR_KEY, new ActionMessage("login.unauthorizedAddress"));
342             addErrors(request, errs);
343         }
344     }
345
346     /* (non-Javadoc)
347      * @see com.sslexplorer.core.actions.CoreAction#getNavigationContext(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
348      */

349     public int getNavigationContext(ActionMapping mapping, ActionForm form, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) {
350         return SessionInfo.ALL_CONTEXTS;
351     }
352 }
353
Popular Tags