1 package org
.argeo
.security
.ui
.rap
;
3 import java
.security
.PrivilegedAction
;
5 import javax
.security
.auth
.Subject
;
6 import javax
.security
.auth
.login
.LoginException
;
8 import org
.apache
.commons
.logging
.Log
;
9 import org
.apache
.commons
.logging
.LogFactory
;
10 import org
.argeo
.ArgeoException
;
11 import org
.eclipse
.equinox
.security
.auth
.ILoginContext
;
12 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
13 import org
.eclipse
.rwt
.RWT
;
14 import org
.eclipse
.rwt
.lifecycle
.IEntryPoint
;
15 import org
.eclipse
.swt
.widgets
.Display
;
16 import org
.eclipse
.ui
.PlatformUI
;
17 import org
.eclipse
.ui
.application
.IWorkbenchWindowConfigurer
;
18 import org
.eclipse
.ui
.application
.WorkbenchAdvisor
;
19 import org
.eclipse
.ui
.application
.WorkbenchWindowAdvisor
;
20 import org
.springframework
.security
.BadCredentialsException
;
23 * RAP entry point with login capabilities. On the user has been authenticated,
24 * the workbench is run as a privileged action by the related subject.
26 public class SecureEntryPoint
implements IEntryPoint
{
27 private final static Log log
= LogFactory
.getLog(SecureEntryPoint
.class);
30 * How many seconds to wait before invalidating the session if the user has
33 private Integer loginTimeout
= 1 * 60;
34 private Integer sessionTimeout
= 15 * 60;
37 public int createUI() {
38 // Short login timeout so that the modal dialog login doesn't hang
40 RWT
.getRequest().getSession().setMaxInactiveInterval(loginTimeout
);
42 if (log
.isDebugEnabled())
43 log
.debug("THREAD=" + Thread
.currentThread().getId()
44 + ", sessionStore=" + RWT
.getSessionStore().getId());
46 Integer returnCode
= null;
49 Display display
= PlatformUI
.createDisplay();
52 final ILoginContext loginContext
= SecureRapActivator
53 .createLoginContext();
54 Subject subject
= null;
55 tryLogin
: while (subject
== null && !display
.isDisposed()) {
58 subject
= loginContext
.getSubject();
59 } catch (LoginException e
) {
60 BadCredentialsException bce
= wasCausedByBadCredentials(e
);
62 MessageDialog
.openInformation(display
.getActiveShell(),
63 "Bad Credentials", bce
.getMessage());
69 ThreadDeath td
= wasCausedByThreadDeath(e
);
75 // if (e.getCause() != null) {
76 // Throwable firstCause = e.getCause();
77 // // log.error("Cause", firstCause);
78 // if (firstCause instanceof LoginException
79 // && firstCause.getCause() != null) {
80 // Throwable secondCause = firstCause.getCause();
81 // if (secondCause instanceof BadCredentialsException) {
82 // MessageDialog.openInformation(
83 // display.getActiveShell(),
85 // "Your credentials are incorrect");
88 // } else if (secondCause instanceof ThreadDeath) {
89 // // rethrow thread death caused by dialog UI timeout
90 // throw (ThreadDeath) secondCause;
93 // } else if (firstCause instanceof ThreadDeath) {
94 // throw (ThreadDeath) firstCause;
98 if (!display
.isDisposed()) {
99 org
.argeo
.eclipse
.ui
.Error
.show(
100 "Unexpected exception during authentication", e
);
101 // this was not just bad credentials or death thread
102 RWT
.getRequest().getSession().setMaxInactiveInterval(1);
106 throw new ArgeoException(
107 "Unexpected exception during authentication", e
);
112 // identify after successful login
113 if (log
.isDebugEnabled())
114 log
.debug("Authenticated " + subject
);
115 final String username
= subject
.getPrincipals().iterator().next()
118 // Once the user is logged in, she can have a longer session timeout
119 RWT
.getRequest().getSession().setMaxInactiveInterval(sessionTimeout
);
121 // Logout callback when the display is disposed
122 display
.disposeExec(new Runnable() {
124 log
.debug("Display disposed");
125 logout(loginContext
, username
);
133 returnCode
= (Integer
) Subject
.doAs(subject
, getRunAction(display
));
134 logout(loginContext
, username
);
138 return processReturnCode(returnCode
);
141 /** Recursively look for {@link BadCredentialsException} in the root causes. */
142 private BadCredentialsException
wasCausedByBadCredentials(Throwable t
) {
143 if (t
instanceof BadCredentialsException
)
144 return (BadCredentialsException
) t
;
146 if (t
.getCause() != null)
147 return wasCausedByBadCredentials(t
.getCause());
153 * If there is a {@link ThreadDeath} in the root causes, rethrow it
154 * (important for RAP cleaning mechanism)
156 protected ThreadDeath
wasCausedByThreadDeath(Throwable t
) {
157 if (t
instanceof ThreadDeath
)
158 return (ThreadDeath
) t
;
160 if (t
.getCause() != null)
161 return wasCausedByThreadDeath(t
.getCause());
166 protected void logout(ILoginContext secureContext
, String username
) {
168 secureContext
.logout();
169 log
.info("Logged out " + (username
!= null ? username
: "")
170 + " (THREAD=" + Thread
.currentThread().getId() + ")");
171 } catch (LoginException e
) {
172 log
.error("Erorr when logging out", e
);
176 @SuppressWarnings("rawtypes")
177 private PrivilegedAction
getRunAction(final Display display
) {
178 return new PrivilegedAction() {
179 public Object
run() {
180 int result
= createAndRunWorkbench(display
);
181 return new Integer(result
);
186 /** To be overridden */
187 protected Integer
createAndRunWorkbench(Display display
) {
188 return PlatformUI
.createAndRunWorkbench(display
,
189 createWorkbenchAdvisor());
192 /** To be overridden */
193 protected Integer
processReturnCode(Integer returnCode
) {
197 /** To be overridden */
198 protected WorkbenchAdvisor
createWorkbenchAdvisor() {
199 return new SecureWorkbenchAdvisor() {
200 public WorkbenchWindowAdvisor
createWorkbenchWindowAdvisor(
201 IWorkbenchWindowConfigurer configurer
) {
202 return new RapSecureWorkbenchWindowAdvisor(configurer
);