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.
So I have a website that uses a cookie to remember the current layout state across visits. Everything was working great until I added a Facebook 'Like' button to the site which generates links that allow users to share a certain UI state (a little confusing but not really relevant to the problem).
The problem is that when I visit the site via one of these Facebook links a second copy of my layout cookie seems to be created (as in, I see two cookies with the same name and different values). This wouldn't be too terrible except that the value of the duplicate cookie appears to be stuck, coupled with the fact that when the user returns to the site the browser remembers the stuck value instead of the most recently set value (so it's kind of like there's a "good" cookie that I can still work with, and a "bad" one which I cannot, and the browser likes to remember the "bad" cookie instead of the "good" cookie). This breaks my layout tracking/remembering functionality.
So there are two questions here:
How do I stop this from happening/why is this happening in the first place?
How do I fix things for any users that already have a stuck cookie (I know I could just pick a new name for the cookie, but I'd rather do it by finding a way to properly unstick the stuck cookie)?
If I use Chrome's developer console after visiting the page in a stuck state, I can see that document.cookie is (formatting added for readability):
layoutState=[{'id':6,'x':8,'y':1525,'z':4,'url':'undefined'}, {'id':1,'x':625,'y':709,'z':2,'url':'undefined'}, {'id':2,'x':8,'y':37,'z':3,'url':'undefined'}, {'id':3,'x':625,'y':1179,'z':5,'url':'undefined'}, {'id':4,'x':626,'y':37,'z':1,'url':'undefined'}, {'id':5,'x':626,'y':357,'z':1000000,'url':'http://m.xkcd.com/303/'}];
WibiyaNotification1=1;
WibiyaNotification213286=213286;
WibiyaNotification213289=213289; wibiya756904_unique_user=1;
JSESSIONID=DONTHIJACKMEPLEASE;
WibiyaProfile={"toolbar":{"stat":"Max"},"apps":{"openApps":{}},"connectUserNetworks":[null,null,null,null,null,null]};
WibiyaLoads=59;
layoutState=[{'id':6,'x':8,'y':1525,'z':4,'url':'undefined'}, {'id':1,'x':625,'y':709,'z':2,'url':'undefined'}, {'id':2,'x':8,'y':37,'z':3,'url':'undefined'}, {'id':3,'x':625,'y':1179,'z':5,'url':'undefined'}, {'id':4,'x':626,'y':37,'z':1,'url':'undefined'}, {'id':5,'x':626,'y':357,'z':6,'url':'http://m.xkcd.com/303/'}]"
Ignore the Wibiya cookies and the JSESSIONID. The stuck cookie is the first 'layoutState' instance, and the one that I can still manipulate in JavaScript is the second 'layoutState' instance. Here is what I get if I change some things around:
layoutState=[{'id':6,'x':8,'y':1525,'z':4,'url':'undefined'}, {'id':1,'x':625,'y':709,'z':2,'url':'undefined'}, {'id':2,'x':8,'y':37,'z':3,'url':'undefined'}, {'id':3,'x':625,'y':1179,'z':5,'url':'undefined'}, {'id':4,'x':626,'y':37,'z':1,'url':'undefined'}, {'id':5,'x':626,'y':357,'z':1000000,'url':'http://m.xkcd.com/303/'}];
WibiyaNotification1=1;
WibiyaNotification213286=213286;
WibiyaNotification213289=213289;
wibiya756904_unique_user=1;
JSESSIONID=DONTHIJACKMEPLEASE;
WibiyaProfile={"toolbar":{"stat":"Max"},"apps":{"openApps":{}},"connectUserNetworks":[null,null,null,null,null,null]};
WibiyaLoads=59;
layoutState=[{'id':1,'x':8,'y':39,'z':1000000,'url':'undefined'}]
The second 'layoutState' has the correct information that I want the browser to remember. However what the browser actually remembers is the value of the first instance.
I've tried unsetting the cookie entirely, which causes the second instance to disappear, but nothing I do seems to get rid of the first instance. I get the same behavior in all major browsers (Chrome, Firefox, IE), which makes me suspect that I must be doing something fundamentally wrong here, but I'm not sure what it is.
You can view the site itself here. Or click here to access it via a Facebook link (should generate a stuck cookie). Any help is much appreciated.
Update:
So the steps to reliably reproduce the error are as follows:
Visit the site via the Facebook-style link
Make some changes to the layout, and then close the tab.
Visit the site via the normal URL.
Your layout from the initial visit should be correctly remembered, so change some things around and then refresh the page. When the page reloads, your changes will no longer be remembered.
I've also noticed that revisiting the site via the Facebook-style URL is able to clear/reset the stuck cookie. So it's like the browser is keeping a separate cookie for each URL path, or something, and not allowing the root page to access the cookie that was set on the other URL path. I thought I might be able to fix this by explicitly setting path=/ on the cookie, but no dice.
Update 2:
I've found that if I set both the path and the domain of the cookie I get different behavior in all browsers:
Firefox - Works correctly now, hooray! Worked correctly once, then broke, boo!
Chrome - No change
IE - Seems to be keeping separate cookies for each URL, so the Facebook-style URL remembers one state, and the standard URL remembers a different state. Both update correctly and independently of each other. This is kind of funky, but still way better than the stuck/broken state.
Dude(tte), there are inconsistencies, and a bug, in your cookie setter.
1. Make sure path and domain is correctly set
The path and domain should be the same for both clearing the cookie and setting it. See your code here:
document.cookie = c_name + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
and compare it to:
var c_value=escape(value) + "; expires=" + exdate.toUTCString(); + "; path=/spring; domain=aroth.no-ip.org";
you will see that the setter has both of them, but the deleter doesn't. You will bring about chaos.
2. Oh, and that nasty semicolon
That second line of code I quoted above, has a semicolon introduced in the middle of a string concatenation expression. Right after exdate.toUTCString(). Kill it. Kill it…now.
At least on my Google Chrome, I managed to get it run correctly, if I set a breakpoint at json = "[" + json + "]"; and modify setCookie before it is executed.
P/S: It was a bizzare debugging experience, where I managed to set 4 layoutState cookies, by fiddling with path & domain.
This may be too simple, but just in case, are the cookies recorded for two different paths? If the URL is different, you may be setting your cookies for a restricted path, so the system would take them differently.
Here is a solution, the / slash help to do not set duplicate cookie of same name
setcookie('YourCookieName','yes', time() + 400, '/');
check in Chrome console -> Resources if your page gets loaded twice. That would be the reason of double cookie.
There is again the problem left after identifying the problem and taking prevention by correctly setting the cookie.
You also need to delete previous incorrectly set cookies in your or in your client's browser.
So observe the cookie set from developer tools and search for path and subdomain and put those explicitly on your code to delete.
function eraseCookie(c_name) {
document.cookie = c_name + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
}
function eraseCookieWithPathDomain(c_name) {
document.cookie = c_name + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;path=/yourpath/to; domain=sub.domain.com";
//you can remove this function call on your second upload if you are confirm that the previous cookie setter expired
}
You may need to call function eraseCookieWithPathDomain right after eraseCookie or even every time after document load depending in your application.
You can add the following key in the AppSettings in the web config file it solves the issue of duplicate cookie.
<!-- Tell ASPNET to avoid duplicate Set-Cookies on the Response Headers-->
<appSettings>
<add key="aspnet:AvoidDuplicatedSetCookie" value="true" />
</appSettings>
This will help avoiding the duplicate Set-Cookie() in Response Headers.
It seems the issue is not a duplicate cookie (cookies overwrite themselves) but a duplication of the DATA in your cookie.
I think you'll have to modify the script that reads the cookie and clean out the duplicate value if it's detected.
In a nutshell, I have a web application which used to be able to set cookies just fine, but it no longer works. The really strange thing is I've used Chrome's debugger to follow what's going on, and it makes it all the way to the "document.cookie = " statement fine.
Further, I haven't changed anything except the content of the cookie (adding more information). I haven't modified the cookie setting logic at all, or even the parameters.
Here's the most recent version of my application: http://asmor.com/scripts/tsrand/alpha/
The relevant bit is lines 147-149, http://asmor.com/scripts/tsrand/alpha/init.js
cookie=JSON.stringify(opt)
log("Cookie: "+cookie);
$.cookie(cookieName, cookie, { expires: 365 });
opt is an object I'm using to store form element values. I convert the object into a JSON string and then store it. Here's an example of what cookie contains in this version of the program:
{"diseaseSelect":".5","soloGame":"checkbox:false","showLog":"checkbox:true","min_Setting":"0","max_Setting":"1","cardBarrowsdale":"Maybe","cardDoomgate":"Maybe","cardDragonspire":"Maybe","cardDreadwatch":"Maybe","cardFeaynSwamp":"Maybe","cardGrimhold":"Maybe","cardRegianCove":"Maybe","min_Thunderstone":"1","max_Thunderstone":"1","cardStoneofAgony":"Maybe","cardStoneofAvarice":"Maybe","cardStoneofMystery":"Maybe","cardStoneofScorn":"Maybe","cardStoneofTerror":"Maybe","min_Monster":"3","max_Monster":"3","cardAbyssal":"Maybe","cardAbyssalThunderspawn":"Maybe","cardBanditHumanoid":"Maybe","cardCultistHumanoid":"Maybe","cardDarkEnchanted":"Maybe","cardDoomknightHumanoid":"Maybe","cardDragon":"Maybe","cardElementalFire":"Maybe","cardElementalNature":"Maybe","cardElementalPain":"Maybe","cardEnchanted":"Maybe","cardEvilDruidHumanoid":"Maybe","cardGiant":"Maybe","cardGolem":"Maybe","cardHorde":"Maybe","cardHumanoid":"Maybe","cardHydraDragon":"Maybe","cardOoze":"Maybe","cardOrcHumanoid":"Maybe","cardTheSwarm":"Maybe","cardUndeadDoom":"Maybe","cardUndeadLich":"Maybe","cardUndeadPlague":"Maybe","cardUndeadSpirit":"Maybe","cardUndeadStormwraith":"Maybe","min_Guardian":"0","max_Guardian":"1","cardDarkChampion":"Maybe","cardDeathSentinel":"Maybe","cardGuardianofNight":"Maybe","cardGuardianofTorment":"Maybe","cardUnholyGuardian":"Maybe","min_Trap":"0","max_Trap":"1","cardTrapDeath":"Maybe","cardTrapDire":"Maybe","cardTrapDraconic":"Maybe","min_Treasure":"0","max_Treasure":"1","cardAmuletTreasure":"Maybe","cardFigurineTreasure":"Maybe","cardUlbricksTreasure":"Maybe","min_Hero":"4","max_Hero":"4","cardAmazon":"Maybe","cardBelzur":"Maybe","cardBlind":"Maybe","cardCabal":"Maybe","cardChalice":"Maybe","cardChulian":"Maybe","cardClan":"Maybe","cardDeep":"Maybe","cardDiin":"Maybe","cardDrunari":"Maybe","cardDivine":"Maybe","cardDwarf":"Maybe","cardElf":"Maybe","cardEvoker":"Maybe","cardFeayn":"Maybe","cardFlame":"Maybe","cardGangland":"Maybe","cardGohlen":"Maybe","cardGorinth":"Maybe","cardHalf-Orc":"Maybe","cardLorigg":"Maybe","cardOutlands":"Maybe","cardPhalanx":"Maybe","cardRedblade":"Maybe","cardRegian":"Maybe","cardRunespawn":"Maybe","cardSelurin":"Maybe","cardSidhe":"Maybe","cardSlynn":"Maybe","cardStoneguard":"Maybe","cardTempest":"Maybe","cardTerakian":"Maybe","cardTholis":"Maybe","cardThyrian":"Maybe","cardToryn":"Maybe","cardVerdan":"Maybe","cardVeteran":"Maybe","min_Village":"8","max_Village":"8","cardAmbrosia":"Maybe","cardAmuletofPower":"Maybe","cardArcaneEnergies":"Maybe","cardBanish":"Maybe","cardBarkeep":"Maybe","cardBattleFury":"Maybe","cardBlacksmith":"Maybe","cardBlessedHammer":"Maybe","cardBluefireStaff":"Maybe","cardBorderGuard":"Maybe","cardBurntOffering":"Maybe","cardChieftansDrum":"Maybe","cardClaymore":"Maybe","cardCreepingDeath":"Maybe","cardCursedMace":"Maybe","cardCyclone":"Maybe","cardDivineStaff":"Maybe","cardDoomgateSquire":"Maybe","cardFeast":"Maybe","cardFireball":"Maybe","cardFlamingSword":"Maybe","cardFlaskofOil":"Maybe","cardForesightElixir":"Maybe","cardFortuneTeller":"Maybe","cardFrostBolt":"Maybe","cardFrostGiantAxe":"Maybe","cardGlowberries":"Maybe","cardGoodberries":"Maybe","cardGreedBlade":"Maybe","cardGuardianBlade":"Maybe","cardGuide":"Maybe","cardHatchet":"Maybe","cardIllusoryBlade":"Maybe","cardLantern":"Maybe","cardLightstoneGem":"Maybe","cardMagiStaff":"Maybe","cardMagicMissile":"Maybe","cardMagicalAura":"Maybe","cardPawnbroker":"Maybe","cardPiousChampion":"Maybe","cardPolearm":"Maybe","cardPolymorph":"Maybe","cardQuartermaster":"Maybe","cardRecurveBow":"Maybe","cardSage":"Maybe","cardScout":"Maybe","cardShortBow":"Maybe","cardShortSword":"Maybe","cardSilverstorm":"Maybe","cardSkullbreaker":"Maybe","cardSoulGem":"Maybe","cardSoulJar":"Maybe","cardSpear":"Maybe","cardSpiritBlast":"Maybe","cardSpiritHunter":"Maybe","cardSpoiledFood":"Maybe","cardTavernBrawl":"Maybe","cardTaxCollector":"Maybe","cardThunderRing":"Maybe","cardTorynGauntlet":"Maybe","cardTownGuard":"Maybe","cardTrader":"Maybe","cardTrainer":"Maybe","cardWarhammer":"Maybe"}
Now, here's the oldest backed-up copy I have: http://asmor.com/scripts/tsrand/backup/2010-09-13/dev/
This copy still works.
Here's the cookie-setting logic from that copy, lines 130-132 http://asmor.com/scripts/tsrand/backup/2010-09-13/dev/scripts/init.js
cookie=JSON.stringify(opt)
log("Cookie: "+cookie);
$.cookie(cookieName, cookie, { expires: 365 });
And an example of what the cookie for that one contains:
{"guardianSelect":".5","trapSelect":"1","monstersSelect":"3","heroesSelect":"4","villageSelect":"8","soloGame":"checkbox:false","useConditions":"checkbox:true","showLog":"checkbox:true","setBase":"checkbox:false","setPromo":"checkbox:true","setWrathOfTheElements":"checkbox:false","cardAbyssal":"Maybe","cardDoomknightHumanoid":"Maybe","cardDragon":"Maybe","cardElementalNature":"Maybe","cardElementalPain":"Maybe","cardEnchanted":"Maybe","cardGolem":"Maybe","cardHorde":"Maybe","cardHumanoid":"Maybe","cardOoze":"Maybe","cardUndeadDoom":"Maybe","cardUndeadSpirit":"Maybe","cardDarkChampion":"Maybe","cardDeathSentinel":"Maybe","cardTrapDeath":"Maybe","cardTrapDire":"Maybe","cardAmazon":"Maybe","cardBlind":"Maybe","cardChalice":"Maybe","cardClan":"Maybe","cardDiin":"Maybe","cardDivine":"Maybe","cardDwarf":"Maybe","cardElf":"Maybe","cardFeayn":"Maybe","cardGangland":"Maybe","cardGohlen":"Maybe","cardLorigg":"Maybe","cardOutlands":"Maybe","cardRedblade":"Maybe","cardRegian":"Maybe","cardRunespawn":"Maybe","cardSelurin":"Maybe","cardThyrian":"Maybe","cardToryn":"Maybe","cardAmbrosia":"Maybe","cardAmuletofPower":"Maybe","cardArcaneEnergies":"Maybe","cardBanish":"Maybe","cardBarkeep":"Maybe","cardBattleFury":"Maybe","cardBlacksmith":"Maybe","cardClaymore":"Maybe","cardCreepingDeath":"Maybe","cardCursedMace":"Maybe","cardFeast":"Maybe","cardFireball":"Maybe","cardFlamingSword":"Maybe","cardForesightElixir":"Maybe","cardGoodberries":"Maybe","cardHatchet":"Maybe","cardIllusoryBlade":"Maybe","cardLantern":"Maybe","cardLightstoneGem":"Maybe","cardMagiStaff":"Maybe","cardMagicMissile":"Maybe","cardMagicalAura":"Maybe","cardPawnbroker":"Maybe","cardPolearm":"Maybe","cardSage":"Maybe","cardShortBow":"Maybe","cardShortSword":"Maybe","cardSpear":"Maybe","cardTavernBrawl":"Maybe","cardTaxCollector":"Maybe","cardTownGuard":"Maybe","cardTrainer":"Maybe","cardWarhammer":"Maybe"}
I'm using libraries for the JSON and for setting/getting the cookie. Both that early version and the latest use the exact same versions of the exact same libraries.
The only thing I can think of is that the cookie has gotten a bit more than twice as long. Before URI encoding, we're talking 4000 characters vs. 1800 characters. Also, I URI encoded the more recent cookie and manually set it myself, and the browser accepted it just fine, and my program loaded it just fine.
I'm completely out of ideas here. Help!
You should really store all this data in a session on the server if possible, rather than having a massive cookie. Then you can simply request data via AJAX or embed it in each page request.
Browsers are only required to provide 4KB of space per cookie, so if you're over that there's a chance it might not be stored.
4096-byte limit; otherwise entire cookie is discarded by IE.
http://support.microsoft.com/kb/306070