browser tab wise session creation using JSP ans Servlets example [duplicate] - javascript

I'm developing a single page jQuery & Backbone.js web app. The backend is a JBoss 6 application server.
Until now we had the following structure:
There is only one servlet (front controller). Every request from the JavaScript client goes through here.
In the servlet - at the first request of a certain JS client - I make a look p to a stateful session bean. For the next requests of this client, I store the result of the look up in an HTTP session container. So every JS client has exactly one stateful session bean. This connection is kept by a session cookie.
Now I have an additional requirement:
When the user has two browser tabs (in one browser), they should have two isolated instances of the web app in every browser tab. Because of that I have a problem with session cookies because this session cookie is for all browser tabs.
I have to change the structure so that:
The servlet has to generate a new session ID for the first request of a certain JS client. This session ID is communicated to the client.
With every POST to the backend the JS client has to send this session ID.
My question is:
Until now I saved the result of the look up in an HTTP Session object and I hadn't to think about generating a session ID. But now I have to store this somewhere else, where?
Has anybody experience with this kind of setting and can help me?
Update:
Thank you BalusC for this very interesting approach.
When I understood you well, this means:
All individual JS clients of the tabs of one browser share one HTTP session object. And in this HTTP session object, every tab has its own entry point. That sounds really good. So I still can use the whole HTTP session infrastructure and don't have to reinvent the wheel.

Autogenerate an unique value on the initial GET request which you store and pass around on every subsequent postback as a hidden input value. Use this unique value as identifier of the session attribute representing the view-scoped data.
During the 1st request on a brand new session, do:
Map<String, ViewData> viewScope = new HashMap<String, ViewData>();
session.setAttribute("viewScope", viewScope);
(the ViewData represents the view-specific data you'd like to track across postbacks on the same view)
During every GET request, do:
String viewDataId = UUID.randomUUID().toString();
viewScope.put(viewDataId, new ViewData());
request.setAttribute("viewDataId", viewDataId);
During generating the HTML, do:
<input type="hidden" name="viewDataId" value="${viewDataId}" />
During every POST request, do:
ViewData viewData = viewScope.get(request.getParameter("viewDataId"));
// Get/set view-specific data in there.
Make sure that jQuery also passes this hidden input around (which shouldn't be a big problem if you already properly use $(form).serialize() or e.g. AjaxForm plugin to ajaxify the forms).
If you're familiar with Java EE's MVC framework JSF, then it may be useful to know that its #ViewScoped annotation works roughly the same as described above. See also a.o. How to choose the right bean scope?

You can use session tracking with URL rewriting. See here:
Session shared in between tabs

Related

Cache API with MVC Views

I have a basic MVC form and I've been trying to use the Javascript Cache API to cache all my css, js, html files so that when users (people in the field) do not have reliable access, they can still use my web form. Obviously I'm using IndexedDB and service workers as well to check for a connection and save locally when a connection is not available, syncing when it is available.
I've gone through some tutorials and everything seems straightforward when dealing with caching actual, physical files (css, html, js). MVC is weird though since you're routing. I created the basix Index, Create, Edit, Details views. When I create an array of URL's to cache such as
var urlsToCache = [
'/App/Details',
'/App/Edit',
'/App/Create',
'/App/Index',
'/App/Content/bootstrap.css',
'/App/Content/site.css',
'/App/Scripts/jquery-1.10.2.js',
'/App/Scripts/jquery.form.js',
'/App/sw.js',
'/App/Scripts/bootstrap.js',
]
.. everything caches except for DETAILS and EDIT. Index and create cache fine. I'm actually surprised the latter two cache at all since they aren't physical files. I'm assuming Details and Edit don't cache because they don't work without querystring parameters.
Is it POSSIBLE to cache these two views at all? Or does anyone know of anything on NuGet that addresses this situation?
I changed this in the GET method for my Edit action to return an empty Model if there was no ID
if (id == null)
{
//return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
return View();
}
This allowed me to load the Edit page without a querystring variable and not get an error message. The page loads with no data but it allows me to cache it. At this point I suppose I would have to tell my service worker to check if the page is online. If it is, route the request normally, else query the local storage and manually plug the values into the fields.
So let this be a lesson to anyone creating Offline-enabled apps with MVC and using Cache API. Get rid of the lines that return bad request errors in your CRUD views if ID numbers aren't passed. Just pass back a blank model to the view (return View()). This allows you to cache your pages. And you'll obviously need to write code to handle the offline retrieval and presentation in code that executes when the page loads, but it will still allow you to utilize the MVC/Razor features when online.
One thing to note: "/App/Edit" will cache. If you load "/App/Edit/2", it won't match a url in your cache so you'll get an offline message. However, you can easily modify your Index page to send the ID via post. Just have a form on the page that goes to the Edit action and change the link to an underlined span with an onclick that sets the value of a hidden field to the ID. You'll have to pass another hidden field to let it know that it needs to retrieve instead of update (since the controller has different GET AND POST actions for Edit. The GET action is useless, but keep it for caching. You're retrieval that you normall would do int the GET is now going to be done in the POST with an if statement to check for your hidden field flag.

Retaining a value from a response in node js

On page load, say for a particular route for (e.g. https://localhost:8000/home/index), a service is called and the response from the service is rendered to the page at the client side.
On the same page, I have a link that pops up a Backbone.js modal and from the modal a click event triggers which hits another url (e.g. https://localhost:8000/home/index2) upon which another service call triggers and the response is rendered to another html page.
On the same html page, I want to display a value which I got from the first service call on page load. However, I am unable to retain that value as there are two different requests each time. Hence, I cannot even append the value from first response to the request object and use it a second time.
You can use JavaScripts Web Storage API to storage information on client browser.
MDN Web Storage API
For example, If you are on the first screen and call a service, store the service information on localStorage
localStorage.setItem('firstService', serviceResponseObject);
Once you are navigated to second page, you can use localStorage to read to previous service information
localStorage.getItem('firstService');
There are multiple ways to store state between requests.
From the server, if you're using say Express etc, you could store the result in a Session. Or you can even store state in the requests query params, or from a POST request.
You could also store some data on the client end, using say Cookies or localstorage.
What you choose really depends, it might be best if you explain in more detail what sort of information your passing between pages.
If it's just a simple value, I would go for using query params.
eg. Just place in your url https://localhost:8000/home/index2?value=123, and then from node.js, req.query.value would have your value.

Persist Local UIWebView Values

*EDIT*
I've done more research and it looks like cookies may also be the answer. I suppose I would add a button to the form inside the embedded html that calls a function to create a cookie for the values. Then I could access this cookie through obj-c using the stringByEvaluatingJavaScriptFromString method. Of course then you run into the issue of expiration, multiple copies of the form not being allowed, etc. So it is a trade-off of features. I'm going to stick with the window.location route because I can store this in a DB and then the user can create another instance of the same form
*EDIT*
I've done some research and I have a vague idea how to accomplish this, but I was curious if there was a better method.
I have a local copy of an html form loading in a UIWebView on this iPad app I am developing. The forms are submitted server-side through xml and parsed there for DB storage, but unfortunately they are pretty lengthy. So I want to let the user save the form in its current state (maybe they only fill it out halfway), and then return to it later.
What I am thinking is that I will have to write some javascript to parse the radio buttons and checkboxes in the form, then pass this data through the window.location trick to the obj-c code. But this is VERY lengthy, and the strings being passed back and forth between JS and Obj-C will be very long. Is there any other way to grab the values of these checkboxes/radio buttons and pass them to the obj-c side to be repopulated later?
How about going via a file? Save the settings/data to a file in JS and access that file in Objective-C land. But I guess you've already thought of this.
But at the end of the day the data has to be passed back and forth regardless of how you do it. Doing it via the window.location trick will be the fastest, and provided there are no limitations imposed by the OS itself is there any reason not to do it this way?
You could encode the data into a blob to make it easier to pass around.
But on the other hand doing it by file route may however be useful if you want the settings to persist if your app gets terminated.
Also you could actually submit the form data but intercept it in Objective-C before it gets sent by using a NSURLProtocol derived class. THe NSURLProtocol class could allow the submission to proceed if it knows the data is complete. But I don't see any point in doing this if window.location doesn't have a size limit.

Asp.net access sessionstate from JavaScript

Our system using HttpContext.Current.Session("Client") to store the current user info.
One property in the session is a roleID i.e. CType(HttpContext.Current.Session("Client"), Client).RoleId
By checking the value of RoleId, the system can identify whether the user can access a couple of pages.
I've validated it in the server-side. But for the easiest way to present the Notice Message I think is using JavaScript.
So is it possible to get the session value in JavaScript (even in a external JavaScript)?
How about Cookie? What is the drawback for adding Cookies for an existing system?
And any other suggestions if you have.
Thx
Yes, I did the validation in server side. Later again, I'll add restrictions in DBs as well.
Result:
I used webMethod inside a web service, caz it is a Master Page.
Thanks for you answer.
but another issue raised:
Trigger/Prevent page event by using asynchronous webmethod return value in JavaScript
please give me some advise on that question as well, thx.
You could do it as a cookie, but it would slow down your round trip for every resource. Hence, I don't recommend this approach.
One option is to have a dynamic page that returns a javascript object in global with the appropriate variables printed out. You then could just include it as a standard script tag.
Another approach is to make an AJAX call.
Keep in mind, you should still always validate the base request and never trust the client.
Sending roles to the client and using JavaScript for business logic based upon these roles is a security risk. Users (hackers) know how to manipulate client-side code to gain access to things they're not supposed to.
I recommend sending down only the content the user has access to or use AJAX to retrieve the content dynamically from the client.
But to answer your question, no, you cannot retrieve session data directly from the client.
You can make ashx page or WCF service and call that with javascript. But don't return roleID and check that ID on client, instead just return true / false if user has access. Use jQuery ajax call to ashx or WCF service, you should find tons of examples on google

How to prevent direct access to my JSON service?

I have a JSON web service to return home markers to be displayed on my Google Map.
Essentially, http://example.com calls the web service to find out the location of all map markers to display like so:
http://example.com/json/?zipcode=12345
And it returns a JSON string such as:
{"address": "321 Main St, Mountain View, CA, USA", ...}
So on my index.html page, I take that JSON string and place the map markers.
However, what I don't want to have happen is people calling out to my JSON web service directly.
I only want http://example.com/index.html to be able to call my http://example.com/json/ web service ... and not some random dude calling the /json/ directly.
Quesiton: how do I prevent direct calling/access to my http://example.com/json/ web service?
UPDATE:
To give more clarity, http://example.com/index.html call http://example.com/json/?zipcode=12345 ... and the JSON service
- returns semi-sensitive data,
- returns a JSON array,
- responds to GET requests,
- the browser making the request has JavaScript enabled
Again, what I don't want to have happen is people simply look at my index.html source code and then call the JSON service directly.
There are a few good ways to authenticate clients.
By IP address. In Apache, use the Allow / Deny directives.
By HTTP auth: basic or digest. This is nice and standardized, and uses usernames/passwords to authenticate.
By cookie. You'll have to come up with the cookie.
By a custom HTTP header that you invent.
Edit:
I didn't catch at first that your web service is being called by client-side code. It is literally NOT POSSIBLE to prevent people from calling your web service directly, if you let client-side Javascript do it. Someone could just read the source code.
Some more specific answers here, but I'd like to make the following general point:
Anything done over AJAX is being loaded by the user's browser. You could make a hacker's life hard if you wanted to, but, ultimately, there is no way of stopping me from getting data that you already freely make available to me. Any service that is publicly available is publicly available, plain and simple.
If you are using Apache you can set allow/deny on locations.
http://www.apachesecurity.net/
or here is a link to the apache docs on the Deny directive
http://httpd.apache.org/docs/2.0/mod/mod_access.html#deny
EDITS (responding to the new info).
The Deny directive also works with environment variables. You can restrict access based on browser string (not really secure, but discourages casual browsing) which would still allow XHR calls.
I would suggest the best way to accomplish this is to have a token of some kind that validates the request is a 'good' request. You can do that with a cookie, a session store of some kind, or a parameter (or some combination).
What I would suggest for something like this is to generate a unique url for the service that expires after a short period of time. You could do something like this pretty easily with Memcache. This strategy could also be used to obfuscate the service url (which would not provide any actual security, but would raise the bar for someone wanting to make direct calls).
Lastly, you could also use public key crypto to do this, but that would be very heavy. You would need to generate a new pub/priv key pair for each request and return the pubkey to the js client (here is a link to an implementation in javascript) http://www.cs.pitt.edu/~kirk/cs1501/notes/rsademo/
You can add a random number as a flag to determine whether the request are coming from the page just sent:
1) When generates index.html, add a random number to the JSON request URL:
Old: http://example.com/json/?zipcode=12345
New: http://example.com/json/?zipcode=12345&f=234234234234234234
Add this number to the Session Context as well.
2) The client browser renders the index.html and request JSON data by the new URL.
3) Your server gets the json request and checks the flag number with Session Context. If matched, response data. Otherwise, return an error message.
4) Clear Session Context by the end of response, or timeout triggered.
Accept only POST requests to the JSON-yielding URL. That won't prevent determined people from getting to it, but it will prevent casual browsing.
I know this is old but for anyone getting here later this is the easiest way to do this. You need to protect the AJAX subpage with a password that you can set on the container page before calling the include.
The easiest way to do this is to require HTTPS on the AJAX call and pass a POST variable. HTTPS + POST ensures the password is always encrypted.
So on the AJAX/sub-page do something like
if ($_POST["access"] == "makeupapassword")
{
...
}
else
{
echo "You can't access this directly";
}
When you call the AJAX make sure to include the POST variable and password in your payload. Since it is in POST it will be encrypted, and since it is random (hopefully) nobody will be able to guess it.
If you want to include or require the PHP directly on another page, just set the POST variable to the password before including it.
$_POST["access"] = "makeupapassword";
require("path/to/the/ajax/file.php");
This is a lot better than maintaining a global variable, session variable, or cookie because some of those are persistent across page loads so you have to make sure to reset the state after checking so users can't get accidental access.
Also I think it is better than page headers because it can't be sniffed since it is secured by HHTPS.
You'll probably have to have some kind of cookie-based authentication. In addition, Ignacio has a good point about using POST. This can help prevent JSON hijacking if you have untrusted scripts running on your domain. However, I don't think using POST is strictly necessary unless the outermost JSON type is an array. In your example it is an object.

Categories

Resources