In my web app I am trying to achieve the functionality, that an admin is able to logout other currently logged in users.
What I have done so far:
- I created a POJO to store significant user information, including a referrence to the users HTTP session.
- This POJO is implementing
HttpSessionBindingListener
- During the login process I put an instance of this POJO into the SessionMap. Via the
valueBound
method I am putting into a static Map, which stores all such logged-in-userinformation (on the unbound-Event I am removing it again - In a seperated admin section I am now able to access the
HttpSession
of a specific user and invalidate it - the logged-out user gets informed via websocket that he has been logged-out
Invalidating the HttpSession
works fine and the mentioned unbound
method is called. However, the problem is that if a in that way logged out user is still able to do AJAX requests. A new instance of hte ViewScoped Bean is created and assigned to the client and the request goes against this new instance.
What I would expect (or what I would like to achieve) is that sth like a ViewExpiredException is thrown instead and redirecting the user to the login page instead.
Or am I missing an important part in my concept?
Would it be enough to set up proper security-constraints in web.xml
or would it just hide the conceptual problem?
(If it's important, the Bean is not a JSF Bean but a CDI ViewScoped bean.)
Application is running on Glassfish 4.1,, Mojarra 2.2.12
SessionBindingListener:
@RequiredArgsConstructor
@EqualsAndHashCode(of = {"user"})
public class UserSessionInfo implements HttpSessionBindingListener {
@Getter private static final Map<UserSessionInfo, UserSessionInfo> sessions
= new HashMap<>(10);
@Getter private final String user;
@Getter private HttpSession session;
@Override
public void valueBound(HttpSessionBindingEvent event) {
UserSessionInfo usi = sessions.remove(this);
if (usi != null) {
HttpSession hs = usi.session;
if (hs != null) {
hs.invalidate();
}
}
this.session = event.getSession();
sessions.put(this, this);
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
sessions.remove(this);
}
}
Login-method
public String login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request =
(HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(username, password);
context
.getExternalContext()
.getSessionMap().put(username, new UserSessionInfo(/* ...*/)));
// ..
}
// ....
return "/index?faces-redirect=true";
}
Admin-Method for logging out some other user:
public void logoff(UserSessionInfo usr) {
EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish(CHANNEL, new DialogMessage(/*...*/));
usr.getSession().invalidate();
}