Managing webapp session data/controller flow for multiple tabs - java

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.

Related

What would a conditional privilege implementation look like using Spring Security?

What I mean by 'conditional' privileges is, for example: Say we have Event e. The user who CREATED Event e should be able to delete Event e and invite additional users to Event e, but only that user.
From tutorials I've seen, permissions and roles seem static, for example:
Doctor has a role doctor, with permissions x, y and z, but that is it...pretty static.
Is there a simple way to conditionally manage permissions with Spring Security?
Or would this be something better suited for the front-end? For example, the view would show a 'delete event' button only if the resource data for that particular Event confirms that the Event creator's ID is in fact the same ID stored in session memory/keychain/whatever for the currently logged in user, type of thing.
Thanks
First of all,
Or would this be something better suited for the front-end?
...show a 'delete event' button only if...
NO. Not as a reliable line of defence, no.
Well that probably depends on a tech stack, architecture etc, but as a rule of thumb, you shouldn't do it. I didn't write servlets/jsp, but I used spring security in a rich client (swing) application and even though we had all the control (I mean, we could guarantee that user cannot access some function no other way than clicking a button), we secured our models, not the gui.
You shouldn't be able to call Entity#delete no matter how you call it - via button click event or calling it directly in a test. In case of web application, imagine you don't display a button, but an attacker knows that button leads to example.com/entity?action=delete URL or something like that, he could access it directly even if you don't render the button.
With regard to the main question, spring security, roughly speaking, has two parts: RBAC and ACL. What you need seems to be the ACL part. Read some howtos and articles about domain security, it's a pretty complex stuff, but it can be suited for your needs for sure (with some effort, of course). What you described in a first paragraph may be achieved easily because every object has it's owner and it can be exploited.
Also, here's a good advice.
Edit: just to clear things up for future visitors. Point was: there should be some logic on the front-end, but it must not be the only security logic. Of course there's no need to clutter UI with buttons leading to functions you can't access.

How to custom page view impression in AEM 6.0?

I see in AEM 6.0 that have a built-in component for page view statistic, displayed as impression column in author site admin. But this built-in does not support for filter the top page view in sites and so on. This one is useful for calculate page view for each page. I'm facing the performance problem for calculate top page view with more than thousand of pages. Anyone have a solution for this one ?. Many thanks and appreciate.
While the impression data initially appears tempting, it is not meant for end-user page view analytics. The CQ integrations with SiteCatalyst, etc are meant for real analytics (or 3rd party solutions, such as Google Analytics).
If you consider the author displays impressions, 1+ publish instances would have to "reverse replicate" impression data back to the author, which would get pushed right back to publish instances.
When you consider the Apache Dispatchers serving up cached pages w/o passing the request to the publish instances, you can understand how even your production publish instances don't see all the traffic, either.
You can create a variant of the page with a selector. Something like: statistics.html.jsp in your page node, then:
http://example.com/a.html is the normal page
http://example.com/a.statistics.html is the page that adds the statistics component.
Finding top 10 most viewed page or sorting all page based on their popularity using Impression service provided by CQ is a bit tricky because of following reasons
It might possible that Page Views is in external system and then you
want to import those data as impression in CQ to have more
application context.
you have to aggregate all data across all publish instances.
It's Slow.
To calculate top page view with more than thousand of pages you have three options
Creating your Own Impression service
You can create your own impression service by extending
com.day.crx.statistics.Entry. Then You can do all the optimizations.
Adobe analytics: If you have thousands of pages then go with adobe
analytics. It will give you the top results and other filtering
options through their Rest Service.
Modify the OOTB service implementation.
You don't want to write your own service but wanted to use OOTB service available to you. Only problem with this is, You have multiple publish instance and some how you want to combine all data into one so that you get accurate picture. It kind of tricky to get all data from all publish instance (through reverse replication) and then combine them on author and then push them over again. However you can use one instance to collect all stat data (king of single source of truth and then replicate it back to all instance every day)
Make sure that you enable page view tracking by adding following line
<cq:include script="/libs/foundation/components/page/stats.jsp" />
Then configure all publish instance to point to one DNS using following config (You can always override this under /apps)
/apps/wcm/core/config.publish/com.day.cq.wcm.core.stats.PageViewStatistics
/apps/wcm/core/config.publish/com.day.cq.wcm.core.stats.PageViewStatisticsImpl
make sure that pageviewstatistics.trackingurl is pointing to single domain (You need to create a domain, something like impression.mydomain.com that will be stand alone CQ instance to take all impression request)
Now you have consolidated page impression on one machine
You can easily write a scheduler which will run every night and reverse replicate all data to author instance.
Once it is an author instance you can use replicator service to replicate to all other publish instance
Then you can tweak some code as mentioned in the custom approach to get popular resources.
For read more about the Custom implementation:
Implementations instruction:

Generating guest access(read/write) link to an otherwise log-in requiring page

I have been working on a GWT application, which is a variation of an issue tracking system. There are some projects, which have some tickes(tasks or issues) assigned to some users. One of the requirements is to provide the administrator with an option to give access to a certain non-user person, to a specific task of a specific project. This can be a read or read/write access.
So, the question is, what are some best practices to achieve this, especially in a GWT application? Are there some specific protocols, or frameworks etc to be used.
My understanding is to generate a unique(non-guessable) url token, map it to the ticket(task, issue). And also, map the token to an access type(read, read/write). Then, load the mapped ticket, with the right access type.
But, i am wondering if there is a out of the box solution to this?
AFAIK there is no ready-solution in GWT.
Basically you will create a history token (i.e. http://MyGWTApp.com/tasks/#!SOME_LONG_UID).
When the user navigates to this URL, you have to check on the backend if the UID is valid. You can do this by using either RPC, RequestBuilder, or rf. Conveniently you can return the access type (red/write) back to the client.
With the access type you can then disable some UI interface elements.
Some things to keep in mind:
For each task/action that goes to the backend you have to check if the UID allows the access pattern (= never trust the client). So you also have to send along the UID with each request.
You can also have to make sure on the backend that when the anonymous users can only carry out the tasks (read/write) that are allowed (= whitelist).

JSP/Spring MVC application

I am writing a web application using JSP/Spring MVC and would need to customize the UI based on the customer using it. I would need to hide/show certain sections of the screen, hide show certain labels and their text boxes and also modify labels based on different customers. Currently we are controlling the hide/show in the JSPs by elements and divs based on the logged in customer. For example:
if (customer= "A")
show this
else
hide this
The code gets cluttered and the JSP will get bloated as we add more customers.
Another alternative I have thought is split a page into sections and control the sections in the same way, but might end up in code repetition accross the JSPs.
For example
if (customer = "A")
jsp:include headerA.jsp
else
jsp:include genericheader.jsp
Another alternative would be to write different JSPs and route based on the client.
Is there a better way to handle this kind of situations. Can someone suggest the best practices to implement such a solution?
Thanks.
A UI that chooses what to do for each user can't possibly scale beyond your users A and B. You need a role-based authentication and authorization system.
Since you're already using Spring, I'd recommend looking at Spring Security and its role based capabilities. There are tags that can help you.
Another way to look at it is that role-based logic like this does not belong in tags. I'd recommend putting it in controllers and let them assemble pages for you.
Another possibility is something like SiteMesh, which allows you to create composite views.
One more: jQuery was born to manipulate the DOM. Use it along with CSS.
First thing it should be based on Role and not based on customer, and each customer will have certain role. It may possible that many customers will have same role and screen access and UI.
Based on role, you can use Spring Secutiry for Authentication and Authorization.
If you need to use Layout differently as per customer role, preferably you should use some Layout Manager such as Tiles, SiteMesh etc.
or use portlets for different login views to different customers
You just stated if person A logs in from one store, vs person B logs in from another. Hate to say it, but that's a role, no matter how you want to spin it, this is related to user authorization.
In terms of how you want to implement it, you could do a variety of things, you could intercept the login request and set a session variable which prepends a string to determine the correct view (i.e. when user a logs in you get customerA, vs customerB, so when rendering the view you'd retrieve the value and render "customerA/index" vs. "customerB/index", etc.
You could also determine the person's roles within the controller and render the appropriate view, although this couples your user roles to your controller logic, which wouldn't be recommended in my opinion.
If this app is going to have a lot of different backends, I'd recommend portlets that way you can write a new backend for each app, rather than bloating your web application with every new store backend.
Those are just a couple ways, hope this helps.

What is the best way to protect user inputs (not yet submitted) from session timeout?

I develop and maintain small intranet web apps(JSP and Resin).
Some users takes so much time to complete the forms that,
when they submit, they lose all their input data because of session timeout.
Currently I prolonged session timeout to 30 minutes and
display count-down clock till session timeout on top of the page, but,
I think their must be better ways to
protect user inputs.
What is the best practices?
Addendum
Our users make several kind of reports with the web-app,
and the whole contents of each report are stored in a JavaBean stored in the session.
As suggested by some, Ajax or iframe should do the quick fix.
I now know that it is better not to abuse session with heavy objects,
but I'm not sure how best to refactor current mess.
Some people suggested to make the web-app stateless.
Any suggestion for refactoring is welcome.
This may or may not be the case with your framework, but I think that if your page just uses AJAX to call the server every five minutes (or whatever), then that will keep your user's session alive. You don't even have to do a partial save of your form this way.
Make your applications stateless on the server side. You can include any state you need to maintain in hidden input fields. If security is a concern then you can encrypt the data before putting it in the field.
An example is putting something like this in your form:
<input type="hidden" name="user" value="bob" />
<input type="hidden" name="currentRecordId" value="2345" />
<input type="hidden" name="otherStuff" value="whocares" />
The main advantage of this is that your web app can do everything it needs to with just that page. It doesn't need any session variables because everything it needs is in the page it just received. Now it doesn't matter how long they take because there is no session to expire.
A secondary advantage is that it reduces the load on your server because it isn't polling your users periodically.
I've only recently needed to look at solutions to this problem.
The direction that looked most promising was using AJAX to periodically check if data was entered, and send it to the server. If the browsers running in your company support AJAX, this is one possibility.
Another possible solution could be to split the forms up, so that each section is small enough to be filled out and submitted within the session timeout.
If you are creating an application for a limited number of users (e.g., a company intranet) and you don't want people to have to keep logging in all day or have them lose their input information when sitting for extended periods of time, you can keep sessions open indefinitely only for people that have their browser open to your website without setting the session timeout to not expire. As soon as they close the website then the session will expire as normal.
What you need to do is add a hidden iframe somewhere on the page. Have the iframe point to a simple html document served by your app server that has a meta tag in it to refresh every 29 minutes (for a session that expires in 30 minutes). This way, as long as the person has your web page open, their session won't expire. However, when they navigate away from your site it will expire as normal. You get unlimited session lengths without the downside of sessions that grow out of control.
I successfully deployed this solution in an enterprise environment at a previous place of employment. The web app replaced an old green screen application and it was unacceptable for them to go to lunch and have the application expire on them, for example.
Let me know if you need more of an example.
I'd recommend looking into a stateless alternative (something that does not rely on session attributes) to what you're doing.
We may be able to help more if we know what exactly it is you're relying on sessions for.
You could store the data in a cookie every once in a while, use Gears as a temporary storage (if the data is complex or requires more than 4K storage) or send the temporary data to the server every n second using AJAX.
Umm..
What about displaying a prompt to the user about the session about to be expired -- save data (say 5 min before), so that they can save the data. This way they know what they have to save and in case the session really needed to be expired, it will be done afterward if they don't respond.
This is an alternative in case when you want to avoid a continuous ping to server using AJAX.
Don't use the session object. This is a cause of all sorts of usability problems - as you are discovering.
It's my golden rule of web application development: don't use the session.
Having said that, use it sparingly for things that just can't be done otherwise.
I would trigger "after a Ajax check that the session is expired" an popup form in a modal window that the User must sign in again, This popup overlay would be over the current page/form. So the data wouldn't be lost.
P.N Update the session token if U have one... in a hidden field.

Categories