I am going to have code running on a site in an iframe which may or may not be cross-domain, and may be duplicated in multiple iframes. I may have code running in the top window, I may not. I want my JS to generate a unique identifier which will be the same if it is generated by my code in any iframe on that page, in multiple iframes, iframes nested in iframes, or in the top window, for the life of that load of the main page only.
It should generate the same identifier when run in any window context of that webpage loading for that user at that time. So if an iframe is removed, another one added should generate the same id.
What is the best information to use for this? It is essentially a 'session' id but needs to be generated in the browser, and be the same for any child iframe generating it. Thanks to anyone who can help!
After some reading, it appears making a browser fingerprint will be the solution. These github projects are helpful:
https://github.com/Valve/fingerprintjs2
https://github.com/ephoton/browser-flag
https://github.com/rynr/fingerprint.js
I'll probably use one of those, or get some ideas for implementing my own simplified solution.
I'm not 100% sure if this answers your question, but my go-to way to generate a random string is partly inspired by MongoDB's way of generating unique object IDs:
var uniqueString = Date.now().getTime() + Math.random();
Unless you have hundreds of thousands of users all running this code at the exact same millisecond, you should be fairly guaranteed a random string.
EDIT
The question mentions running code in the top window. With this, there are multiple solutions that could work:
Use the PostMessage API to send all iframes on the page the same random id
Deploy the iframe with the random id as a query string (e.g. http://www.example.com/mypage?id=123)
If, however, you are unable to execute code in the top window, you will have to do things server-side. Here I'm not too certain of how I'd do it, since I'm not sure what you're using on the back-end, but in Node.js you could check the req object. It will contain things like the user's IP address, their useragent string, the date of the request, etc. Concatenating the IP address, useragent string, and maybe the referring page (i.e. the page your user is viewing that loaded the iframes) should give a unique ID for all frames on a given page for a given user.
Related
I am looking for a way to use Jquery (or any other open source script) to pull the URL of a particular webpage. I am working on a service that will pull the original URL of any webpage - consider a scenario where I load google.com but have entered yahoo.com in the address bar (without pressing enter key) - the script should be able to validate if the the URL on the address bar is the same as the actual URL or if it is different.
There is no way to do this. And there better not be any in the making. There is no reason to need such information, and it's a violation of user privacy.
No dear, Absolutely no way to do this.
and i agree with #bjb568 , its definitely violation of user privacy.
you can get the current page URL in your script.
But why you need this kind of functionality.?
i will advise you to find any alternative of your requirement,
You can get the current location of the page using regular Javascript, but I do not think you can get the currently typed address bar, although I do not see where you should ever need to.
In response to everyone on here saying it is a breach of user privacy: I don't think grabbing the URL or the typed address bar on the current page is a breach of privacy or security unless you are somehow able to change the address bar to make it seem like you are on a different site - like being on Google.com and it saying you are on Yahoo.com. But, from the OP's original question, it just seems like he wants to get the information; not change it.
Using Javascript, you can use var location = document.location.href
The closest you can get to change the addressbar is window.history.pushState(), but browsers have a security settings that do not allow domains outside of the current domain to be used.
My first question that comes to mind: "Why on earth does he want to do that???" If it was possible you would have to interact with each browser directly which is not possible.
jQuery is just a client-language that interprets with each browsers "engine" (that handles rendering of html, javascript etc) and not the browser itself (menus, settings etc). Secondly, if it would work: How often would you check? Each keypress? Every 10 seconds? It would not be doable in a proper way - even if it was possible.
I think you should rethink your issue and try to explain why you want to do this. It might be other (better) solutions that would handle your issue in a better way.
I would like to create some javascript that will only run on a given domain. We want to give each of our subscribers a bit of javascript that they can only run on their domain. The javascript will create an iFrame and bring in a page, etc.
If the javascript is placed on a different domain, an error is thrown and the script stops and the iFrame page will not load. Before you say this is not possible, it is done by Google Maps.
So, in short, we would like to mimic what Google Maps is doing. You register a domain with Google, they give you code that has a key and if you place this code on any other domain, it will not work. How do they do it?
The hostname property of window.location contains a hostname. It can be faked, so you could try checking the Referer header when serving your script, too – but absolutely do not rely on that.
You could also do a bit of a validity check by making a request to a nonexistent page on that domain – it’ll be blocked by cross-origin policies if the developer is cheating.
Another possible solution is to use the IP address, since the code is placed on a server.
I've made an license script with this method, and so far only 2 mad customers, but that was because they moved their website to another server without me telling it.
I think its good to have a client check, but that can be by-passed, if someone figures out how the script works. So, always do a server-side check.
Here is some code I use for the license check, its server based.
Also, I removed some functions that are specific to my website.
I can't figure out how to post code so I put it on pastebin.
http://pastebin.com/ftEDXhTP
When you give the user their snippet of code, on the server-side, store a specific domain name with an identifier you give to the user. You will likely generate this code automatically, like StackOverflow did with your question. They called it 19850979, so let's use that as the identifier you give to your user for example. When the user puts the snippet in place, when they use the iframe for example, the URL referenced in the iframe must contain the identifier.
Not sure what your server-side technologies are, but generally this concept works across the board:
For example... your server saves this information in its database:
user-example-domain.com,19850979
Your user's iframe ( which you generate and give them ) references:
your-serving-domain.com/iframeloader/19850979
Now, in the code that handles /iframeloader/ and receives 19850979 as the identifier, compare the hostname of the referrer. This is the Referer header, which is an HTTP header field:
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
If the hostname of the referrer is value, continue loading the iframe. If not, abort and show some kind of informative error message.
I have a DNS, and each computer has a website to make different folders / documents accessible in a different way than just browsing to that computer. For example, \Media takes me to the media servers pages (Music, Movies, etc.), and \Aurora takes me to the media server's website. Instead of it displaying "Aurora" in the address bar, however, I would like to use a script to replace it with "Aurora - Media Server Website, (server information)." I would really like to learn this method, I tried to look somewhere and it mentioned JavaScript would probably be the easiest way to do this. This would be helpful if I actually knew JavaScript =p If there is an easier way to do this, that would also be much appreciated =]
In a nutshell, I want the address of a website, //Aurora, hosted on a local DNS server to appear as "Aurora - Media Server Website (server information)." What would be a possible way to implement this?
Just use the replaceState method of window.history in JavaScript like so:
window.history.replaceState({}, '', url);
(params are: data (object), title (string), url (string));
I do it all the time to modify the URL, to remove the query string when using AJAX.
If you want to change the hostname then you have to change the DNS so that the machine gets the name you want. You can't use spaces or parenthesis in hostnames though.
The closest you can come with JS is the history API which only lets you modify the local part of the URI.
It is not possible to change the contents of the address bar due to security reasons (Phishing websites would exploit this heavily).
I would suggest simply changing the title of the page.
<title>Title goes here</title>
If you want to change it using javascript (for some reason) you can do this:
document.title = "The new title goes here.";
This is sort of a generic "Good Idea/Bad Idea question".
My scenario: I am writing an ASP.NET MVC3 app that is just 1 page (one View/Controller). This view shows a grid of "Cases" and when a user clicks one of these Cases, I use jquery ajax ($.ajax) to swap out the visible portion of the page and load the details of this Case (but never change the page).
Still with me? Thanks!
Now, once this new Case detail view is shown, the user can edit the Case in one of many ways. Change the priority, change the status, etc. I am using jquery's ajax function for this as well.
My question: How should I store the Case ID? Is it ok to store it in the HTML? Is there a better place to store it?
All of the Cases have a Guid ID, and currently when the Case details are loaded (using ajax) I add a custom attribute to the Case detail view <div> so I know the Case ID. This means that the Case ID is visible to anybody viewing the page source. I thought about using jQuery's .data() function to store it, which wouldn't be visible to page source, but would be accessible from Firebug other inspector tools.
What is the best practice for this? I really can't imagine how my user's would do anything with the Case ID, but I am trying to be a bit paranoid here.
Thanks in advance for any thoughts! And thanks for reading this novel!
There's very little you can do about things which the browser gets to see in any fashion, since code and data in the DOM are not protected from the user.
Obviously you don't want to send anything to a user who is not allowed to see that information - so you don't want to do any client-side filtering of data that is dependent upon user role.
But as for internal data, you just have to protect your perimeter - methods can't accept ids which are mismatched (i.e. an account id which is only valid for a different customer being submitted) - but there's very little you can do about the ids themselves.
By sending the case ID from the server to the browser, you are giving it to the user. If you don't want the user to have the case ID, don't send it to the browser.
I'd provide some sort of sanitized, "imaginary" ID if you're that concerned. If this were running in a loop, I'd suggest basing it on the loop index.
Ultimately however, you'll need to use some sort of unique identifier on the Case that will identify it in ajax calls to the database.
Really though, I've done the same thing before and just encoded the ID field in the markup, and it's rarely mattered. This ID is only a harmful thing to have out in the open if your security is lax. If you've secured your database and have a decent level of security on the app, then you should be fine. If you haven't, then you have bigger things to worry about than markup.
So I have two documents dA and dB hosted on two different servers sA and sB respectively.
Document dA has some JS which opens up an iframe src'ing document dB, with a form on it. when the form in document dB is submitted to a form-handler on server sB, I want the iframe on page dA to close.
I hope that was clear enough. Is there a way to do this?
Thanks!
-Mala
UPDATE: I have no control over dA or sA except via inserted javascript
This isn't supposed to be possible due to browser/JavaScript security sandbox policy. That being said, it is possible to step outside of those limitations with a bit of hackery. There are a variety of methods, some involving Flash.
I would recommend against doing this if possible, but if you must, I'd recommend the DNS approach referred to here:
http://www.alexpooley.com/2007/08/07/how-to-cross-domain-javascript/
Key Excerpt:
Say domain D wants to
connect to domain E. In a nutshell,
the trick is to use DNS to point a
sub-domain of D, D_s, to E’s server.
In doing so, D_s takes on the
characteristics of E, while also being
accessible to D.
Assume that I create page A, that lies withing a frame that covers the entire page.
Let A link to yourbank.com, and you click on that link. Now if I could use javascript that modifies the content of the frame (banking site), I would be able to quite easily read the password you are using and store it in a cookie, send it to my server, etc.
That is the reason you cannot modify the content in another frame, whose content is NOT from the same domain. However, if they ARE from the same domain, you should be able to modify it as you see fit (both pages must be on your server).
You should be able to access the iframe with this code:
window["iframe_name"].document.body
If you just want the top-level to close, you can just call something like this:
window.top.location = "http://www.example.com/dC.html";
This will close out dA and sent the user to dC.html instead. dC.html can have the JS you want to run (for example, to close the window) in the onload handler.
Other people explained security implications. But the question is legitimate, there are use cases for that, and it is possible in some scenarios to do what you want.
W3C defines a property on document called domain, which is used to check security permissions. This property can be manipulated cooperatively by both documents, so they can access each other in some cases.
The governing document is DOM Level 1 Spec. Look at the description of document. As you can see this property is defined there and … it is read-only. In reality all browsers allow to modify it:
Mozilla's document.domain description.
Microsoft's domain property description.
Modifications cannot be arbitrary. Usually only super-domains are allowed. It means that you can make two documents served by different server to access each other, as long as they have a common super-domain.
So if you want two pages to communicate, you need to add a small one-liner, which should be run on page load. Something like that should do the trick:
document.domain = "yourdomain.com";
Now you can serve them from different subdomains without losing their accessibility.
Obviously you should watch for timing issues. They can be avoided if you establish a notification protocol of some sort. For example, one page (the master) sets its domain, and loads another page (the server). When the server is operational, it changes its domain and accesses the master triggering some function.
A mechanism to do so would be capable of a cross-site scripting attack (since you could do more than just remove a benign bit of page content).
A safe approach would limit to just the iframe document emptying/hiding itself, but if the iframe containing it is fixed size, you will just end up with a blank spot on the page.
If you don't have control over dA or Sa this isn't possible because of browser security restrictions. Even the Flash methods require access to both servers.
This is a bit convoluted but may be more legitimate than a straight XSS solution:
You have no control over server A other than writing javascript to document A. But you are opening an iframe within document A, which suggests that you only have write-access to document A. This a bit confusing. Are you writing the js to document A or injecting it somehow?
Either way, here is what I dreamed up. It won't work if you have no access to the server which hosts the page which has the iframe.
The user hits submit on the form within the iframe. The form, once completed, most likely changes something on the server hosting that form. So you have an AJAX function on Document A which asks a server-side script to check if the form has been submitted yet. If it has, the script returns a "submitted" value to the AJAX function, which triggers another js function to close the iframe.
The above requires a few things:
The iframe needs to be on a page hosted on a server where you can write an additional server-side script (this avoids the cross-domain issue, since the AJAX is pointing to the same directory, in theory).
The server within the iframe must have some url that can be requested which will return some kind of confirmation that the form has been submitted.
The "check-for-submitted" script needs to know both the above-mentioned URL and what to look for upon loading said URL.
If you have all of the above, the ajax function calls the server-script, the server-script uses cURL to go the URL that reflects if the form is done, the server-script looks for the "form has been submitted" indicators, and, depending on what it finds, returns an answer of "not submitted" or "submitted" to the ajax function.
For example, maybe the form is for user registration. If your outer document knows what username will be entered into the form, the server-side script can go to http://example.org/username and if it comes up with "user not found" you know the form has yet to be submitted.
Anything that goes beyond what is possible in the above example is probably outside of what is safe and secure anyway. While it would be very convenient to have the iframe close automatically when the user has submitted it, consider the possibility that I have sent you an email saying your bank account needs looking at. The email has a link to a page I have made which has an iframe of your bank's site set to fill the entire viewable part of my page. You log in as normal, because you are very trusting. If I had access to the fact that you hit submit on the page, that would imply I also had access to what you submitted or at the very least the URL that the iframe redirected to (which could have a session ID in or all sorts of other data the bank shouldn't include in a URL).
I don't mean to sound preachy at all. You should just consider that in order to know about one event, you often are given access to other data that you ought not have.
I think a slightly less elegant solution to your problem would be to have a link above the iframe that says "Finished" or "Close" that kills the iframe when the user is done with the form. This would not only close the iframe when the user has submitted the form, but also give them a chance to to say "oops! I don't want to fill out this form anyway. Nevermind!" Right now with your desired automatic solution, there is no way to get rid of the iframe unless the user hits submit.
Thank you everybody for your answers. I found a solution that works:
On my server, I tell the form to redirect to the url that created the iframe.
On the site containing the iframe, I add a setInterval function to poll for the current location of the iframe.
Due to JS sandboxing, this poll does not work while the url is foreign (i.e. before my form is submitted). However, once the url is local (i.e. identical to that of the calling page), the url is readable, and the function closes the iframe. This works as soon as the iframe is redirected, I don't even need to wait for the additional pageload.
Thank you very much Greg for helping me :)