This is how I create my cookie with Javascript and after that redirect to cart page.
var d = new Date();
d.setTime(d.getTime() + (1 * 24 * 60 * 60 * 1000));
var expires = ";expires=" + d.toUTCString();
var product = { productId: btn.value, colorId: productColorId, quantity: 0 };
products.push(product);
document.cookie = "products=" + JSON.stringify(products) + expires + "; path=/; SameSite=strict";
window.location.href = "cart";
and I can find this cookie in my browser in cookie section, but in server side I get nothing.
At first I use this code and I get null.
string products = HttpContext.Request.Cookies["products"];
After that I try this code
if (HttpContext.Request.Cookies.TryGetValue("products", out cookieValue))
{
// TODO: use the cookieValue
}
else
{
// this cookie doesn't exist.
}
and always it runs else, It seems, even don't find cookie.
Is there any suggestion?
According to this documentation,a can optionally be set in double quotes and any US-ASCII characters excluding CTLs, whitespace, double quotes, comma, semicolon, and backslash are allowed.
Try the following changes in your javascript ,use encodeURIComponent() to convert double quotes
document.cookie = "products=" + encodeURIComponent(JSON.stringify(product)) + expires + "; path=/; SameSite=strict";
The screenshot of the cookie value got in the server-side
In response to a comment, Cookie headers in javascript is forbidden, which means it cannot be set programmatically. Only the browser may set it, and it may choose to not send cookie information along with the HTTP request depending on their browser settings. (Typically inside privacy settings)
First I would confirm that the cookie header is indeed being sent. You can usually find this out by using the browser's web inspector and looking at network request. Here is a screenshot in chrome:
If you don't see the cookie header then I would advise double checking browser privacy settings to ensure cookies are enabled and disabling ad/tracking blockers if you have them installed. If this is a case, unfortunately there isn't much you can do other than beg the user to change their settings or disable their ad blockers.
If you DO see the cookie header, then this suggest that it may be a problem in the back-end code, but I'm not familiar with ASP.NET so I can't really comment on that.
Hope this helps
I'm creating cookies which are intended to be shared all across mysite.
This is the code that creates such cookies:
var setCookie = function(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+d.toUTCString();
var path ="path=/;";
document.cookie = cname + "=" + cvalue + ";" + expires + ";" + path;
};
It looks pretty straight forward, and I'm using path=/ to indicate that I want to create or modify always the same cookie all along my site.
The problem is that it is creating one cookie for each URL. With a Mozilla plugin I can see the following:
Cookie Name Value Path
timer_is_enabled true /
timer_is_enabled false /foo
timer_is_enabled true /foo/bar
Which is causing my many bugs because the variables which are being accessed are not one and only, but many independent ones.
Any idea why I'm getting this behavior?
Your code should work as expected, at least regarding the path attribute. Those other cookies may be remnants from earlier tests (sadly, there's normally no way to track the creation date of a given cookie since browsers don't normally keep such information).
I suggest you remove all current cookies from the browser and try again.
That function works ok for me. Ran the following:
setCookie('myCookieKey', 'myCookieValue', 10);
And I got the following:
It sounds simple and I think it should be simple, but somehow I don't get it to work...
I want to set a Cookie using Javascript and this Cookie should be removed when the user quits the browser. Setting the cookie and getting the value is not the problem. But when I quit the browser and reopen it, the cookie is still there (Firefox).
I use jQuery and the Cookie-Plugin.
Here is my test code:
$(document).ready(function(){
$('#output').append( '<li>initialize...</li>' );
var $cookieVal = $.cookie('testCookie');
$('#output').append( '<li>check cookie...</li>' );
if(!$cookieVal) {
$('#output').append( '<li>set cookie...</li>' );
$.cookie('testCookie', 'eat cookies', { path: '/' });
//console.log( $.cookie() );
} else {
$('#output').append( '<li>cookie is already set...</li>' );
$('#output').append( '<li>cookie value: '+$.cookie('testCookie')+'</li>' );
}
});
Please find the working example at jsFiddle.
I am beginning to wonder if your testing method might be the problem here. So, I am going to write this in a specific way.
Actual Answer: Browser Setting
In Firefox, Options>General>When Firefox starts>"Show my windows and tabs from last time" is going to preserve your previous session. Change this setting to see that this is indeed working as it is supposed to. Firefox is prolonging your session. For further information, see this "bug": http://bugzilla.mozilla.org/show_bug.cgi?id=530594
There are similar settings in most browsers that probably behave the same way.
Original Answer:
I created a fiddle, http://jsfiddle.net/8Ahg2/ that uses document.cookie rather than jquery cookie plugin. Here is how you test this. (source below)
copy the following URL to your clipboard: http://fiddle.jshell.net/8Ahg2/show/
Completely close your browser of choice - this should be browser independent.
Open your browser, paste the url. The first time it should say: check cookie...
set cookie...
Refresh the page, notice that it should now say the value of the cookie ("test")
Close your browser completely again.
Navigate to the URL that should still be in your clipboard. *Do not refresh the page on the first view, it should again say 'check cookie...
set cookie...'
js
$(document).ready(function () {
$('#output').append('<li>initialize...</li>');
//this regex gets the "name" cookie out of the string of cookies that look like this: "name=test;var2=hello;var3=world"
var cookieVal = document.cookie.replace(/(?:(?:^|.*;\s*)name\s*\=\s*([^;]*).*$)|^.*$/, "$1");
$('#output').append('<li>check cookie...</li>');
if (!cookieVal) {
$('#output').append('<li>set cookie...</li>');
document.cookie = "name=test";
} else {
$('#output').append('<li>cookie is already set...</li>');
$('#output').append('<li>cookie value: ' + cookieVal + '</li>');
}
});
There is some code that worked for me. It should expire when you close the browser because of the date to expire being before now:
var vEnd = new Date();
vEnd.setDate(vEnd.getDate() - 1);
var endOfCookieText = "; expires=" + vEnd.toGMTString() + "; path=/";
document.cookie = escape('testCookie') + "=" + escape("eat cookies") + endOfCookieText;
FIDDLE MODIFIED
Note that the fiddle gives a bunch of load errors on the console for me.
I want users to browse my site from only one tab in their browser. How can this be done? Would I use javascript and cookies?
For example, I have a website: www.example.com - and I want my clients to only be able to visit the site from one single tab in one browser. If they open another tab and load the site (or a subpage of the site) - I want an alert "Can't open multiple instances", and then redirect them to an error page.
Once thing to note - if the user changes the address from www.example.com/action/door/mine.aspx to www.example.com - that should work fine, because the user is in the same (original) tab.
Any help will be appreciated. Thanks in advance.
I've created a simple solution for this. The master page layout creates a tab GUID and stores it in sessionStorage area of the tab. The using an event listener on the storage area I write the tab GUID to the sites localStorage area. The listener then compares the tabs GUID to the one written to site storage and if they differ then it knows more than one tab is open.
So if I have three tabs A,B,C then click something in tab C, tab A and B detect another tab is open and warn user of this. I haven't yet got to fixing it so the last tab used get's notification, work in progress.
Here's the JS I have in master page, plus in the login page I have a localStorage.Clear to clear last tab from previous session.
// multi tab detection
function register_tab_GUID() {
// detect local storage available
if (typeof (Storage) !== "undefined") {
// get (set if not) tab GUID and store in tab session
if (sessionStorage["tabGUID"] == null) sessionStorage["tabGUID"] = tab_GUID();
var guid = sessionStorage["tabGUID"];
// add eventlistener to local storage
window.addEventListener("storage", storage_Handler, false);
// set tab GUID in local storage
localStorage["tabGUID"] = guid;
}
}
function storage_Handler(e) {
// if tabGUID does not match then more than one tab and GUID
if (e.key == 'tabGUID') {
if (e.oldValue != e.newValue) tab_Warning();
}
}
function tab_GUID() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
function tab_Warning() {
alert("Another tab is open!");
}
Note: It's IE9+
Hope this helps.
UPDATE - 2020
Client side implementation:
We can make use of Broadcast Channel API which allows communication across browsing contexts (windows, tabs, frames or iframes) provided both contexts are from same origin.
A simple implementation to detect 2nd tab loading the website from the 1st tab:
//in entry point of your app (index.js)
const channel = new BroadcastChannel('tab');
channel.postMessage('another-tab');
// note that listener is added after posting the message
channel.addEventListener('message', (msg) => {
if (msg.data === 'another-tab') {
// message received from 2nd tab
alert('Cannot open multiple instances');
}
});
This doesn't use localStorage or cookies and it even works if 1st tab is offline and 2nd tab is being loaded.
Note: This is not supported in Safari & IE11 yet :(
UPDATE - 2022
From March 2022, it is now officially supported on Safari 🥳
Take a note on its browser compatibility.
However, there's a polyfill available that does the job.
EDIT2:
It's the exact thing which is mentioned at this answer, You need 2 IDs:
One random one
One consistent one (this will be our SSID actually, since you limit tabs of a single browser, it's better to get generated form browser's unique parameters)
You can generate consistent one from browser's user-agent or get it from server-side. store both of them server-side.
Store the random one in window.name property which is tab-specific.
Send a heartbeat every 1~2 seconds to your server containing both consistent ID and random one. if server fails to receive the heartbeat, it cleans up database and de-register dead clients.
on every browser's request, check window.name for the value. if it were missing, check with the server-side whether if the previous tab is closed or not (cleaned from database).
If yes, generate a new pair for client if no, reject them.
Two suggestions on top of my mind:
Server-side (better): provide all your clients, a user name and password. request them on their first visit of your site to enter with their credentials. then on every other request, check for whether user with said credentials is already logged in or not.
Client *
|
|
Server ---> Check whether
Already logged
or not?
______________
| |
yes no
| |
permit reject
them them
Client-side: If you really need a strong check of this, use evercookie to store an already-logged-in cookie on client's machine.
Side-note: Do know that every attempt in client side is not secure at all! client-side should help server-side, it shouldn't be used as the one and only source of security. even evercookies can be deleted so, give my first suggestion a go.
**EDIT:**
Evercookie is really doing a good job at storing most secure zombie cookies ever but since the library itself is a little bit heavy for browsers (storing a cookie takes more than 100ms each time) it's not really recommended for using in real-world web app.
use these instead if you went with server-side solution:
Way around ASP.NET session being shared across multiple tab windows
Kiranvj's answer
Extending rehman_00001's answer to handle the case where you want the alert on the new tabs instead.
const channel = new BroadcastChannel('tab');
let isOriginal = true;
channel.postMessage('another-tab');
// note that listener is added after posting the message
channel.addEventListener('message', (msg) => {
if (msg.data === 'another-tab' && isOriginal) {
// message received from 2nd tab
// reply to all new tabs that the website is already open
channel.postMessage('already-open');
}
if (msg.data === 'already-open') {
isOriginal = false;
// message received from original tab
// replace this with whatever logic you need
alert('Cannot open multiple instances');
}
});
I know this post is pretty old, but in case it helps anybody, I recently looked into basically doing the same thing using localStorage and sessionStorage.
Similar Anthony's answer, it sets an interval to make sure the originating tab keeps the entry fresh, so that if the browser crashes or somehow closes without calling the unload event (included in the comments but not part of the code for testing purposes), then there would just be a short delay before the application would run properly in a new browser window.
Obviously, you would change the "tab is good", "tab is bad" conditions to do whatever logic you want.
Oh, and also, the createGUID method is just a utility to make the session identifier unique... it is from this answer to a previous question (wanted to make sure I wasn't taking credit for that).
https://jsfiddle.net/yex8k2ts/30/
let localStorageTimeout = 15 * 1000; // 15,000 milliseconds = 15 seconds.
let localStorageResetInterval = 10 * 1000; // 10,000 milliseconds = 10 seconds.
let localStorageTabKey = 'test-application-browser-tab';
let sessionStorageGuidKey = 'browser-tab-guid';
function createGUID() {
let guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
/*eslint-disable*/
let r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
/*eslint-enable*/
return v.toString(16);
});
return guid;
}
/**
* Compare our tab identifier associated with this session (particular tab)
* with that of one that is in localStorage (the active one for this browser).
* This browser tab is good if any of the following are true:
* 1. There is no localStorage Guid yet (first browser tab).
* 2. The localStorage Guid matches the session Guid. Same tab, refreshed.
* 3. The localStorage timeout period has ended.
*
* If our current session is the correct active one, an interval will continue
* to re-insert the localStorage value with an updated timestamp.
*
* Another thing, that should be done (so you can open a tab within 15 seconds of closing it) would be to do the following (or hook onto an existing onunload method):
* window.onunload = () => {
localStorage.removeItem(localStorageTabKey);
};
*/
function testTab() {
let sessionGuid = sessionStorage.getItem(sessionStorageGuidKey) || createGUID();
let tabObj = JSON.parse(localStorage.getItem(localStorageTabKey)) || null;
sessionStorage.setItem(sessionStorageGuidKey, sessionGuid);
// If no or stale tab object, our session is the winner. If the guid matches, ours is still the winner
if (tabObj === null || (tabObj.timestamp < new Date().getTime() - localStorageTimeout) || tabObj.guid === sessionGuid) {
function setTabObj() {
let newTabObj = {
guid: sessionGuid,
timestamp: new Date().getTime()
};
localStorage.setItem(localStorageTabKey, JSON.stringify(newTabObj));
}
setTabObj();
setInterval(setTabObj, localStorageResetInterval);
return true;
} else {
// An active tab is already open that does not match our session guid.
return false;
}
}
if (testTab()) {
document.getElementById('result').innerHTML = 'tab is good';
} else {
document.getElementById('result').innerHTML = 'tab is bad';
}
window.addEventListener('load', function () {
if (localStorage.getItem('web_browser') == null) {
// new tab
localStorage.setItem('web_browser', 'true');
window.addEventListener('unload', function() {
localStorage.removeItem('web_browser');
})
} else {
// duplicate tab
return;
}
})
Put this script at the beginning of html pages, where you don't want users to duplicate current page or tab.
The same problem (and solution) : https://sites.google.com/site/sarittechworld/track-client-windows
Similar :
http://www.codeproject.com/Articles/35859/Detect-and-prevent-multiple-windows-or-tab-usage-i
The best way to solve this is to have one-time session IDs.
Eg, each page contain a session ID, that is valid for one visit, is unique, and random.
When clicking any one link, it will use & invalidate the session ID, and the new page will have a new session ID.
This will force the user to always browse in the newest window or tab, and also prevents session stealing over the wire.
Any attempt to reuse a old session ID should immediately kill also the active session IDs for that user.
Its also important to store, in the session management system, which pages is accessible from page X. So if page X (with session ID abc) contains links to page 1, 2 and 3, any attempt to visit page 4 with session ID abc, will fail and also kill the session.
This will force the user to always have one single session track, and always follow the logic on the site. Any attempt to go forward, back, using history or log entires, or opening multiple windows or tabs, will fail and logout the user in all windows, tabs and devices.
All this can be completely implemented on server-side, without any client-side logic.
Why do you want to do this?
Could try to do some ugly hacking, but the result would be: There is no way you could completely suppress this behaviour.
This could not be solved by JavaScript, because there is always the possibility that the user has disabled JavaScript in his browser, or allows only a certain subset.
The user could open a new browser, use a different computer, etc. to visit multiple pages at once.
But more important:
Also, your site would be the only site that has this behaviour and for this reason this will confuse everybody which uses your site, because it doesn't work like a web site should work. Everybody who tries to open a second tab will think: "This is odd. This website sucks because it different then websites should be. I will not come again!" ;-)
I wrote this to stop a call center page from being accessed in multiple tabs. It works well and is purely client-side. Just update the else if part to do what you want if it detects a new tab.
// helper function to set cookies
function setCookie(cname, cvalue, seconds) {
var d = new Date();
d.setTime(d.getTime() + (seconds * 1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
// helper function to get a cookie
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
// Do not allow multiple call center tabs
if (~window.location.hash.indexOf('#admin/callcenter')) {
$(window).on('beforeunload onbeforeunload', function(){
document.cookie = 'ic_window_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
});
function validateCallCenterTab() {
var win_id_cookie_duration = 10; // in seconds
if (!window.name) {
window.name = Math.random().toString();
}
if (!getCookie('ic_window_id') || window.name === getCookie('ic_window_id')) {
// This means they are using just one tab. Set/clobber the cookie to prolong the tab's validity.
setCookie('ic_window_id', window.name, win_id_cookie_duration);
} else if (getCookie('ic_window_id') !== window.name) {
// this means another browser tab is open, alert them to close the tabs until there is only one remaining
var message = 'You cannot have this website open in multiple tabs. ' +
'Please close them until there is only one remaining. Thanks!';
$('html').html(message);
clearInterval(callCenterInterval);
throw 'Multiple call center tabs error. Program terminating.';
}
}
callCenterInterval = setInterval(validateCallCenterTab, 3000);
}
I have an app for Android (and hopefully later iPhone) that is based on Javacript and is made into an app using Phonegap/Applaud.
Unfortunately, setting and getting cookies is not working on Android, and this might be particular to the Android environment. I was advised that using "local storage" might be more reliable.
However, I knew nothing about local storage until this morning, and so I'm struggling to get aquainted. From what I gather, it's basically just another place to save data with a different syntax. For my situation, I don't think it gives me any advantages over cookies other than the fact that Android is forcing me to use it. As a result, I'm hoping I can still leverage my existing code for setting and getting cookies, and not have to take on a whole new approach.
Surely I can just do a test in my Javascript to see if there is local storage, and if so, store and retrieve my cookie data there, and if not, then just use cookies as normal?
Note 1: I searched Stack Overflow for similar questions, and there was this one which at first seems exactly what I'm talking about, but it's too terse so I can't parse it to know what I should do with it. Also, I think it assumes the presence of libraries and code that I don't think I have. I also looked at this question but I think it's doing the reverse of what I'm after.
Note 2: This is my current code for getting and setting cookies (procured from somewhere on the web. Up until the Android problem, was rock solid reliable):
function getCookie(c_name)
{
var c_start = document.cookie.indexOf(c_name + "=");
if (document.cookie.length > 0)
{
if (c_start !== -1)
{
return getCookieSubstring(c_start, c_name);
}
}
return "";
}
function setCookie(c_name, value, expiredays)
{
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie = c_name + "=" + escape(value) +
((expiredays === null) ? "" : ";expires=" + exdate.toUTCString());
alert("this is document.cookie: " + document.cookie);
}
Have a look at http://diveintohtml5.info/storage.html. The history might not be very interesting at all, but it at least provides an excellent link list to other tutorials in the further-reading section.
So, now to your code. The first thing to mention is that localStorage has no expire - it's persistent (until the user manually cleans everything). If you'd like to use some shorter storage, you might also use sessionStorage, which has the same interface but last only until the browser is closed.
Rephrasing your code is simple:
function getCookie(c_name) {
return localStorage.getItem(c_name);
}
function setCookie(c_name, value, expiredays) {
return localStorage.setItem(c_name, value);
}
localStorage behaves exactly like a regular Object.
localStorage.somekey = "My data"; // set
alert(localStorage.somekey); // get
delete localStorage.somekey; // unset
The only real difference between localStorage and any other Object is that it is pesistent. Any page from the same origin can access the values in the object, and they even survive if the browser is closed.
They are superior to cookies in every way for data storage, because they don't get sent to the server with every single request (although that's not to say cookies are useless - both have their advantages).
It's really simple ;)
I used the information in the other answers, so this isn't a different answer, but I just thought it would be helpful to others to see the complete code I ended up with. This can be pretty much dropped in as a replacement for using cookies (as I did). It tests for local storage, and uses that if present, and uses cookies if it isn't.
Note you'll probably want to take out the alerts when implementing it.
function getCookie(c_name)
{
if(typeof localStorage != "undefined")
{
return localStorage.getItem(c_name);
}
else
{
var c_start = document.cookie.indexOf(c_name + "=");
if (document.cookie.length > 0)
{
if (c_start !== -1)
{
return getCookieSubstring(c_start, c_name);
}
}
return "";
}
}
function setCookie(c_name, value, expiredays)
{
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
if(typeof localStorage != "undefined")
{
alert("This place has local storage!");
localStorage.setItem(c_name, value);
}
else
{
alert("No local storage here");
document.cookie = c_name + "=" + escape(value) +
((expiredays === null) ? "" : ";expires=" + exdate.toUTCString());
}
}