I posted this question java-vaadin-14-detect-user-leave-closes-tab-f5-etc but I think I asked the wrong questions.
I want to limit each signed-in user, to just one (1) active browser tab, or UI for that matter.
Someone told me to use VaadinSession.getCurrent().getUIs(), but this list is incremented by 1 (or 2 if #Push is enabled) every time the user refreshes the page. This means I can't check if this list contains more than one (or 2).
I'm lost on this! With native java applications and a built-in login system, I can EASILY limit each user to just one (1) session. It's harder with a browser. Or maybe it isn't?
You could maybe register a UI init listener which closes all other UIs in the same session whenever a new UI is initialized?
See:
Tutorial: UIInitListener
Javadoc
On the other hand, I would also be curious to understand why you want to prevent users from opening multiple tabs.
Related
I have been asked previously this and not sure what is supposed to be the answer, the question is suppose you had an online trading page, that allows you to buy and sell stocks whereas all the stocks are constantly changing via ajax, how do you implement to check if the user/session is still active?
I had suggested to use javascript, where when the user is not keying or not moving the mouse it will prompt that the session will end, and log out the user
Second alternative, would be to put a session-timeout in web.xml whereas once the user has session timed out it will require the user to relogin.
But both answers I have provided seemed wrong. What is the proper, standard way to handling session on a dynamic page? (i.e buying airplane tickets or stock trading page?)
Can anyone provide example?
Project Context
Client requires that the users of the site (when logged in and are able to view their personal information) be forced to be logged out if they try to navigate using the browser's navigation buttons.
My Research
Searching around on SO seems to indicate that most of the problems people have is to "stop" people from hitting the browser's back button when they're logged out, like this and this. The difference is that I need to "stop" the users from navigating backwards in history (and even forward as well, though I don't see how the users can go forward in history if they can't go back in the first place) even when they are logged in, making it compulsory that they use the provided navigation.
The Solution I Have In Mind
I'm thinking of capturing the browser's event when a user hits the back button and logging them out then. However, as discussed here it seems like you can only "do it" using Javascript and not using server-side code. My qualm with this approach is that users can bypass it merely by disabling Javascript on their browsers.
My Question
So my question is - Is there a way I can capture the browser event on the server-side and log them out there? If not, what are the alternatives to achieving my objective?
I'd say that your best option is tracking the session.
You make the client send you the timestamp of when the request was processed by your server, or even simpler: a user dependent counter (which you send each time to the client), and server-side keep track of the last timestamp/counter sent.
If the user clicks the back button, he will send you an old timestamp/counter instead of the last current one, and you can then log him out server side.
This should do the trick.
In order to make sure the trick is done and making it javascript independent, I'd say you could place this value in a hidden parameter, or maybe as a hidden field form, so the user doesn't see it but it always gets sent to your server.
I hope this helps!
What I did was to create a single page, 1 html document, then use AJAX to navigate the whole site. When a user hits the back button it takes you to the index page, which is the log in page. To log in I use AJAX which I do redirect on the server side only. The only problem is when a user hits the forward button but the good thing is no JS no navigation.
If the requirement is trap browser navigation buttons and log them out - the easier alternative is never show these navigation buttons in the first place. What is the use if the user cannot use or click back and forward.
Open a new browser without a toolbar, menu bar from you webapp. When the user closes the window, trap the event and logout the session. This way - the solution would remain simple.
My 2c
Relying on javascript is not a good practice, since it is on client side and what runs on client side can always be bypassed by client.
You should instead use session timeout.
Sorry, fetch the buttons themselfe isnt possible.
Since this is a security-problem a solution (without javascript) would be:
to use encoded pages who warn on navigation out-of or into an unencoded-page. Even the mutual authentication might fit your needs.
If I understand correctly your question:
You can't avoid the user to send a request to your server, the user has full control of his/her browser unless you want to ship a custom altered version for an intranet crew (from open-source browser projects).
Without javascript the the only thing you can do is to send a specific parameter via GET when clicking in the required nav button. If the parameter is present you allow the view of the next/prev page, otherwise the user is logged out.
Obviously the user can bypass that by using the browser developer tools. But there is no way you can fully control user UI behavior at this level.
If i am right then you are talking about NO-Cache in broswer.
you can set all these like following:
response.setHeader("pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Cache-Control", "no-store");
response.addDateHeader("Expires", -1);
response.setDateHeader("max-age", 0);
response.setIntHeader ("Expires", -1);
prevents caching at the proxy server
response.addHeader("cache-Control", "private");
And then you can define a filter who checks session on every page. When a user logs in then set an attribute in session and on logout remove it.
I'm currently researching the best method of solving an issue I'm having and was wondering if you could help.
I have a user profile section in my website that I want to make a bit more secure.
I have an issue where when a user logs in, if they click the back button it takes them back to the login page but they're still logged in. How can I have it log the user out and take them to the logout page?
Thanks for your help
I'm not sure you are trying to do the right thing. Users know and use the back button, and it is helpful to them if that button takes them back to what they were doing beforehand. Having it automatically log users out breaks some basic assumptions about how web applications work, and I don't recommend that you do this.
Also, the problem is worse than you think it is. You mentioned users who use the back button, but what about users who use right-click-open-in-new-tab to open several tabs viewing your application, then switch back and forth between the tabs?
That being said, here is a way you can achieve what you want. You need to track most-recently-viewed-page in the user's session on the server. Each time you get a new request, compare against the cached value in the session and if it's not a page that could have navigated here, clear out the session and display the login page. Another way the same thing is achieved is to generate a key as each page is displayed (a large random number will do) which is passed on the subsequent request, and when any page is requested and it doesn't have the most recent key then clear the session and display the login page.
If by mistake user presses the F5 OR
refresh button after login , he should stay on the same page. Right now he is
redirected to login page.
I have used following code to stay on same page.
But I would not like to warn the user on this situation by writing
event.setMessage() in onWindowClosing() method. I just want to make
functionality which will feel the user that nothing has happended even
if by mistake he done browser refresh.
I am looking to avoid unwanted pop-up given by [OR HOW TO HANDLING EVENT ON CANCEL MANUALLY OF CREATED POPUP SO THAT WILL NOT RELOAD i.e. of com.google.gwt.user.client.Window.confirm("Do you really want to exit?")]
Window.addWindowClosingHandler(new Window.ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
//how to prevent sending reload request OR [on cancel button MANUALLY]
}});
In some comments above Activities and Places were mentioned as a solution for your problem. And of course it is a nice and modern one. You will find more details on GWT's documentation for these.
But if you do not want to go down that road, another solution is to use the history mechanism provided by GWT. Each "page" (rather part) of you application shall have a specific token. All you have to do then, is to create a History change handler and render the appropriate objects according to the token passed by the user's reload action. If you want to have some "memory" between user's log-outs (but not browser restarts) you can save this token in local storage and use it after user's log-in to direct her to the last page she was at.
I have a Java web application which stores some data in the session. The data in the session changes as the user interacts with the application (e.g. flow is managed by a controller, each controller has several form pages, on each form page some data is updated in the session and flow goes to the next form page).
The problem is that some users are opening more than one tab to the application, each tab with a different step in the flow. At this point data in the session is messed up since the tabs share the same session (app uses cookie managed sessions).
Telling the users to use different browsers to avoid sharing the same session id (e.g. one Firefox window and one IE window) is not an option since surely at some point somebody will forget to do this and instead use tabs, thus messing up their data.
Adding some verifications that detect that another flow is requested from another tab and display a message to the user saying this is not allowed is not an option either since it pisses of the users and we don't want that do we? :D
The fact is that using another tab is useful for the users because they are more efficient in what they use the application for, so I am keeping this option. But the question now is how best to manage the one session data for the more tabs?
What I thought of, was to have the controller generate a token when it starts the flow and pass this token to each form page which in turn sends it back to identify itself. If another tab requests the same controller action when there is an ongoing flow then generate another token and pass that around.
Basically, I want each flow to have a token and inside the session I won't just keep one set of data but have a set of data for each token and then match requests based on the token.
Now the problem is that this approach will need a lot of rewritings to the application and I was wondering if there is a best practice for managing such a situation or can someone suggest other approaches. I am open to ideas.
Have you encountered this situation? How did you handle it?
This is usually done by assigning a windowId for each tab/window and passing it on each request. Jsf supports this via orchestra. Spring mvc will support it in the next version.
I recently needed this for a simple case, so I implemented it myself. Took half an hour. However, my scope was very limited:
pass a windowId with each request, and return it back for the next request. The first time - generate it.
for any attribute you want to store in the session, put a Map<String, Object> where the key is the windowId
This is exactly what Seam was created to handle. In Seam there's a concept called a Conversation which basically does exactly what you are explaining. Conversations are basically are a way to divide the Session into many pieces that can expire at some timeout. You can look at the source code for org.jboss.seam.core.Manager class to see how it's actually implemented and get inspired ;)
Depending on the complexity of your application, you may want to investigate implementing tabs within your application. This gives you wholesale control over the flow, while still providing users with the functionality they want. I'd argue it's, bugwise, the most robust solution, since you won't have a dependency on the way the browser handles sessions, minimising the number of "known unknowns".
Of course, there'll be potentially a large upfront cost to this, depending on how your application is structured. Without more information about your app, you're the best placed person to decide.
You can also try to wrap your application inside Adobe Air
And then limit your web application to be only accessable from this air. By doing this you dont need to consider the web browser fragmentation and their unique behaviour.