I try to do log out function in JSF 2.0. First I give AUTH_KEY for logging user. After log out I remove this user's AUTH_KEY.
My problem is not working log out for the user session that don't remove.
Section of login function:
if (startupInfo.getConnectionId().equals("success")) {
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap()
.put(AUTH_KEY, loggedUserInfo.getUserId());
return "success";
}
Logout
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(AUTH_KEY);
return "logout";
}
You should invalidate the HTTP session in your logout method. Removing the user info only doesn't kill the session:
HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
if (session != null) {
session.invalidate();
}
Related
here I have a change password page. And I will log the user out once the password has been changed successfully but I have to inform user that the password has been changed successfully before I log him/her out. How should I do the trick? Below is my code:
#RequestMapping(value = "/changepassword", method = RequestMethod.POST)
public String change(Model model, String oldPassword, String newPassword, Principal principal) throws NoSuchAlgorithmException {
//Some method
return "redirect:/somename/j_spring_security_logout";
}
}
I guess it is a simple trick but I just can't figure it out..
I see 2 options:
1.Just make an ajax call to change the password. And then redirect on client side instead of server side. For example (mnemo code in javascript)
ajaxCall.success = {
showMessage("Your session will be terminated. Please login again.")
//wait for 3 seconds and then redirect
setTimeout(function(){ window.location = "/somename/j_spring_security_logout" }, 3000);
}
2.Keep the code as is, just add a request parameter on redirect:
return "redirect:/somename/j_spring_security_logout?notify_about_password=true";
On your logout page add some extra-logic to handle this request parameter.
I met an error when hardcode try to logout with shiro.
user do login and logout not through web login/logout url, but backend link.
when login, it works.
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(request.getParameter("username"), request.getParameter("password"));
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
but when i try to logout, with error:
public void userLogout(String sessionId){
SecurityManager securityManager = SecurityUtils.getSecurityManager();
Subject.Builder builder = new Subject.Builder(securityManager);
builder.sessionId(sessionId);
Subject subject = builder.buildSubject();
if (null != subject) {
try {
subject.logout();
} catch (SessionException e) {
// TODO: handle exception
}
}
}
but met error [org.apache.shiro.session.UnknownSessionException: There is no session with id , then how to manually colse a shiro session?
You shouldn't try to recreate the session and then operate it, you should get the session via the security manager, using the thread the user was logged into, like so:
SecurityUtils.getSubject().logout();
If you somehow want to call logout from a different thread, you can use the SessionDAO interface, but you need to do extra configuration to have shiro use a SessionDAO as described here:
http://shiro.apache.org/session-management.html#SessionManagement-SessionStorage
When you have configured it correctly you can do stuff like:
DefaultSecurityManager securityManager = (DefaultSecurityManager) SecurityUtils.getSecurityManager();
DefaultSessionManager sessionManager = (DefaultSessionManager) securityManager.getSessionManager();
Collection<Session> activeSessions = sessionManager.getSessionDAO().getActiveSessions();
for (Session session: activeSessions){
if (sessionId.equals(session.getId()){
session.stop();
}
}
Hi I have been unable to solve the following problem in Wicket 6.*:
In our webapp we are using wicket-auth-roles to manage authentication/authorization. When session expires, user should be redirected to a page set by getApplicationSettings().setPageExpiredErrorPage(SomePage.class) on his next action. However, if the user tries to access a page which doesn't allow guests, he is redirected to a login page skipping the PageExpiredPage altogether.
My question is - how can I display "Session has expired." message to the user?
Among other things, I have tried session.info("message") during onInvalidate phase of session's lifecycle, however the feedback message is then rendered on the first page after login (not on the login page).
Thank you for your anwsers.
You could use a RequestCycleListener to record when a PageExpiredException is thrown.
public class ExceptionMapperListener extends AbstractRequestCycleListener {
#Override
public IRequestHandler onException(RequestCycle cycle, Exception ex) {
if (ex instanceof PageExpiredException) {
// Record in session or request cycle
// OR
// Create a RenderPageRequestHandler yourself and add a page parameter
// See DefaultExceptionMapper#internalMap(Exception)
}
return null;
}
}
// In Application#init():
getRequestCycleListeners().add(new ExceptionMapperListener());
ORINAL ANSWER
(kept because it could still help...)
I haven't tried it myself since I don't use wicket-auth-roles, but try overriding the method AuthenticatedWebApplication#restartResponseAtSignInPage() with something like this:
if (isSessionExpired()) {
PageParameters params = new PageParameters();
params.add("showSessionExpired", true);
throw new RestartResponseAtInterceptPageException(getSignInPageClass(), params);
} else {
throw new RestartResponseAtInterceptPageException(getSignInPageClass());
}
And then in the SignInPageClass, display the desired message if the showSessionExpired page parameter is present.
I'm not sure how you implement isSessionExpired(), but you seem to have that part already covered.
OR
Depending on how you implemented isSessionExpired(), maybe you could do the following in your SignInPageClass:
if (sessionExpired()) {
session.info("message")
}
After bernie put me on the right path, I eventually figured out a solution to the problem:
First it is required to override RequestCycleListener:
public class SessionExpiredListener extends AbstractRequestCycleListener {
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) {
if (handler instanceof IPageRequestHandler) {
IPageRequestHandler pageHandler = (IPageRequestHandler) handler;
HttpServletRequest request = (HttpServletRequest) cycle.getRequest().getContainerRequest();
//check whether the requested session has expired
boolean expired = request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid();
//check whether the requested page can be instantiated with the current session
boolean authorized = Session.get().getAuthorizationStrategy().isInstantiationAuthorized(pageHandler.getPageClass());
if (expired && !authorized) {
throw new PageExpiredException("Session has expired!");
}
}
super.onRequestHandlerResolved(cycle, handler);
}
}
Check for authorized prevents the session-expired message from displaying on log-out or when accessing unprotected pages.
Finally, you must register your listener and PageRequestHandlerTracker in your WebApplication:
getRequestCycleListeners().add(new SessionExpiredListener());
getRequestCycleListeners().add(new PageRequestHandlerTracker());
can you please tell me how to redirect to next page after successfully login in GWT?
I have created the service interface and its implementions but dont know how to redirect the page after login authentication.
Share your views guyz.
and also tell me how to get sessiontimeout and then redirect automatically to login page in gwt.
Thanx
You can use Window.Location.replace(String newURL) to switch pages.
As for the session timeout, that depens on what kind of session management you are using.
The easiest would be to include the information "session expired" in every RPC call you make, for example with a custom exception:
Server
public String myRpcCall() throws SessionExpiredException {
if(!SessionManager.isSessionValid()) { // depends on your session management
throw new SessionExpiredException;
}
return some_stuff(); // whatever you want to do
}
Client
public doCall() {
AsyncCallback<String> cb = new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
if(caught instanceof SessionExpiredException) {
// inform the user and redirect to login page
Window.Location.replace("login.html");
}
// handle other errors
}
// TODO onSuccess(String)
};
service.myRpcCall(cb); // your rpc call goes here
}
I have three JSF 2.0 web modules and I need to redirect to the login page when the session expires.
I have tried it using a HttpSessionListener, it is calling the sessionDestroyed() event method, but I am not able to forward/redirect the request in there. I think it is becasue there are no HttpServletRequest and HttpServletResponse objects.
I also tried it using a PhaseListener, but it results in a "too many redirects" error in the webbrowser.
public class SessionListener implements PhaseListener {
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
public void beforePhase(PhaseEvent event) {
if (!FacesContext.getCurrentInstance().isPostback()) {
try {
System.out.println("Session Destroyed");
FacesContext.getCurrentInstance().getExternalContext().redirect("login.jsf");
}
catch (Exception e) {
System.out.println("error" + e);
}
}
}
public void afterPhase(PhaseEvent event) {
try {
System.out.println("Session Created");
}
catch (Exception e) {
System.out.println("error" + e);
}
}
}
Why do those attempts not work and how can I solve it the best?
It's not possible to send a redirect at exactly the moment when the session is expired. The client has namely not sent any HTTP request at that moment which you could then respond with a redirect.
You should just keep your existing authentication mechanism which redirects to the login page when the user is not logged-in anymore. You can at best improve it by adding a check if the user is been redirected to the login page because the session has been expired, or just because he has never logged in before (i.e. it's a fresh new request).
You can check for that by if HttpServletRequest#getRequestedSessionId() doesn't return null (which means that the client has sent a session cookie and thus assumes that the session is still valid) and HttpServletRequest#isRequestedSessionIdValid() returns false (which means that the session has been expired at the server side). You can do that in the very same filter where you're checking for the logged-in user (you do already have one, right? or are you using container managed authentication?).
User user = (User) session.getAttribute("user");
if (user == null) {
String loginURL = request.getContextPath() + "/login.jsf";
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
response.sendRedirect(loginURL + "?expired=true");
} else {
response.sendRedirect(loginURL);
}
} else {
chain.doFilter(request, response);
}
And then in the login.xhtml page check for it
<h:panelGroup rendered="#{param.expired}">
<p>You have been redirected to the login page, because your session was expired.</p>
</h:panelGroup>
Your phase listener approach makes by the way no sense. It indeed sends a redirect on every single request causing it to run in an infinite loop. The restore view phase has absolutely nothing to do with the session expiration.
Try to use
FacesContext.getCurrentInstance().getApplication().getNavigationHandler().
handleNavigation(context, null, "LoginForm");
But note that you should use Servlet Filter for these purposes, it's better to do not any redirection from PhaseListener because it's really error prone.