I try to delete this cookie:
First of all a bit of background. This is a token for verification on different sites within the same domain. I make the central login page. This page is working fine, except the log out. Every other cookie, I want to delete, gets deleted by JQuery cookie $.removeCookie('cookieName'). And I know, I can't delete this from the JavaScript, because of the secure-flag.
So I tried deleting it from a controller method. I call this method via ajax from JavaScript.
$.ajax({ur:'/Login/ExpireToken'})
I can see that it works in the Chrome Console Network Tab.
public void ExpireToken()
{
Response.Cookies.Remove("crowd.token_key");
}
But this, I don't know why, makes a new cookie, with the same name, empty value, the whole domain of the login page and no flags set.
So I tested, if the backend can find the cookie I want.
public string ExpireToken()
{
return Response.Cookies["crowd.token_key"].Value;
}
It returns the correct value and doesn't create a new/false one.
After this I tried to set the expires field to one day in the past or to now. I don't know, why this should work, because the expiration date of this cookie is already in the past.
public void ExpireToken()
{
Response.Cookies["crowd.token_key"].Expires = DateTime.Now.AddDays(-1d);
}
And guess what, it doesn't work. It does literally nothing.
Other ways that don't work
if (Request.Cookies["crowd.token_key"] != null)
{
var c = new HttpCookie("crowd.token_key");
c.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(c);
}
As per the doc, you are doing things right in your las attemp, the one setting the expiration date to yesterday. Quote:
The technique is to create a new cookie with the same name as the
cookie to be deleted, but to set the cookie's expiration to a date
earlier than today. When the browser checks the cookie's expiration,
the browser will discard the now-outdated cookie
I would put a breakpoint and debug to check cookie names, if everything is fine, perhaps the web browser is missbehaving.
HttpCookie aCookie;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i<limit; i++)
{
cookieName = Request.Cookies[i].Name;
aCookie = new HttpCookie(cookieName);
aCookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(aCookie);
}
Related
Okay so this one has me stumped. I have written a function that reads the value of a cookie. The logic is
check Response.Cookies in case it has just been written
otherwise read from Request.Cookies to get the previous value
If the cookie has just been written then all is good, and I get the value. However if the cookie has not been written on this visit - it appears to blank the value of the already store cookie.
What?
Here is the code
Note the write happens in a controller
public static void PersistCookie(string cookieName, string cookieValue, bool persistent)
{
var cookie = new HttpCookie(cookieName, cookieValue)
{
Path = "/",
HttpOnly = true,
};
if (persistent)
cookie.Expires = DateTime.Now.AddMonths(6);
HttpContext.Current.Response.SetCookie(cookie);
}
Note the read happens ina partial view
public static string ReadCookieValue(string cookieName, bool checkResponseFirst)
{
if (checkResponseFirst && HttpContext.Current.Response.Cookies[cookieName] != null &&
HttpContext.Current.Response.Cookies[cookieName].Value.HasValue())
return HttpContext.Current.Response.Cookies[cookieName].Value;
return HttpContext.Current.Request.Cookies[cookieName] != null ? HttpContext.Current.Request.Cookies[cookieName].Value : "";
}
It almost seems that just by checking if a cookie has a value, it messes things up.
Thoughts?
Okay so after much more searching on the web, a good work colleague cam up with the following
it looks like I have come across a curiosity in .NET.
Check out this article
http://www.codeproject.com/Articles/3106/On-The-Care-and-Handling-of-Cookies
If you try to access a cookie that doesn't exist in the Response.Cookies collection, it will be created with an empty string in the Value and an Expires date of 01-Jan-0001 00:00. Strangely, it also creates a matching cookie in the Request.Cookies collection if one doesn't already exist.
So if you look at a cookie in the Response then you are indirectly overwriting the cookie on the client machine with an empty cookie, due to expire when the browser closes
So my problem is solved (or should that be unsolvable). As it turns out I have a workaround using the ViewBag but I am glad I was not going crazy!
Thanks for you help
I am not sure you can set cookies in partial views. When setting the cookie with Response.SetCookie, the information is returned to the browser in the Set-Cookie HTTPHeader field. I don't think partial views can set this value, try inspecting your applications response with Fiddler2, after calling Response.SetCookie.
I usually set my cookies with plain Javascript.
I need to delete authentication cookie manually (Instead of using FormsAuthentication.SignOut whcih for some reasons does not work). I tried
System.Web.HttpContext.Request.Cookies.Remove(cookieName); // for example .ASPXAUTH
System.Web.HttpContext.Response.Cookies.Remove(cookieName); // for example .ASPXAUTH
FormsAuthentication.SignOut(); // I don't know why this one does not work
Neither of those command work. In fact Response cookies are empty and request cookie contains the cookie I want to delete when the following commands are executed it no longer contains the cookie I deleted but in browser the cookie still exists and I am able to do things that authorized users can even after signing out.
Try:
if (Request.Cookies["MyCookie"] != null)
{
var c = new HttpCookie("MyCookie")
{
Expires = DateTime.Now.AddDays(-1)
};
Response.Cookies.Add(c);
}
More information on MSDN.
c.Expires = DateTime.Now.AddDays(-1);
This does not clear cookies instantly.
Use this: c.Expires = DateTime.Now.AddSeconds(1);
This will clear cookies instantly.
I am working on a voting mechanism application in my MVC project, I have a requirement that the users are allowed to vote only once in a browser, if he reaches the voting page for the second time in the same browser he shouldnot be able to vote but if in another browser he logins and he should be able to vote again. To do that I have used the Cookies to handle this scenario. What I did was I have added the UserID to the cookie and in the View page i am checking whether Vote button is visible or not. My view is
#if ((ViewData["CookieData"] == null) || (ViewData["CookieData"].ToString() != Session["LoginPersonID"].ToString()))
{
<button name="button" value="Insert" onclick="return confirm('Are you sure you want to submit your choices ?.');">Vote Now!!</button>
<br />
#Html.ActionLink("Back to Home Page", "EmployeeHomePage", "Employee", new { logedinperson = Session["LoginPersonID"] }, null);
}
and My Controller is
public void AddCookie()
{
HttpCookie MyCookie = new HttpCookie("MyCookie", Session["LoginPersonID"].ToString());
MyCookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(MyCookie);
ViewData["CookieData"] = MyCookieCollection;
}
when the First User say PersonA logins in Firefox and votes, his personid is stored in the cookie, so if he tries to reach the voting page again the Vote button will be invisible, but then he tries open on Google Chrome he can then vote.Thats also working as expected. Now when the PersonB login in Firefox and votes his personid is updated in the cookie, so he also cannot vote in the same browser for the second time. But my exact problem is when the PersonA logins again to Firefox he is able to vote because the cookie has been updated with the PersonB's id. So is there anyway how can I restrict both PersonA and PersonB if they have voted already in a browser.
One problem that I see is that you never read the cookie from the request. Your controller is always creating the cookie and sending it back with the response. Instead you should first check to see whether a cookie exists and then act accordingly.
The other aspect is that if you want the cookie to be per account you need to create a different cookie for each account (i.e. construct the cookie name based on the userid or username), or to store all ids/usernames in the cookie and then check each against each one.
The problem is that you don't distinguish between users when naming your cookie. There should be one cookie per user OR you should build a list of users in that single cookie -- but keep in mind that a cookie is limited to 4K in size.
So if you change the line
HttpCookie MyCookie = new HttpCookie("MyCookie",
Session["LoginPersonID"].ToString());
to something like this
var userName = Session["LoginPersonID"].ToString();
HttpCookie MyCookie = new HttpCookie("MyCookie-" + userName,
"Voted");
then it should work (bearing in mind that you also have to modify the code that reads the cookie).
The idea
Store both the IDs in one cookie. When the cookie is an ID list (e.g. comma-separated), it could hold voting restrictions on more than one person. You have to check that the person trying to vote is not in the list.
Of course this works only under assumption that no ID contains chosen delimiter, in this case comma. If comma is not the case, choose pipe or whatever character satisfies this property.
Algoritm
Cookie mechanism is designed to store key-value pairs. Both key and value are strings. If you want to store a comma-separated list of IDs in your cookie, you have to join them using comma as a delimiter (String.join(",", ids)). First read the original value of your cookie, split it in commas, then add the new ID (if not already there) and then join the list and update the cookie.
Implementation
public void AddCookie() {
HttpCookie MyCookie = new HttpCookie("MyCookie");
var userName = Session["LoginPersonID"].ToString();
var originalCookieContents = ViewData["CookieData"].ToString();
var ids = new HashSet<String>(originalCookieContents.Split(','));
ids.Add(userName);
MyCookie.Value = String.Join(",", ids);
MyCookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(MyCookie);
ViewData["CookieData"] = MyCookie.Value;
}
Do not forget to update your view code accordingly! Construct HashSet ids and use its Contains method.
I am using c# and mvc. I am trying to write a cookie to the user browser. But after a refresh of the browser the cookie disappears.
This is my code for writing the cookie:
movieCookie = new HttpCookie(cookieName);
movieCookie.Value = "test;
movieCookie.Expires = DateTime.Now.AddDays(30);
//add the cookie
HttpContext.Current.Response.Cookies.Add(movieCookie);
and the one for reading the cookie:
//check if such cookie exist
HttpCookie movieCookie = null;
if (HttpContext.Current.Request.Cookies.AllKeys.Contains(cookieName))
movieCookie = HttpContext.Current.Request.Cookies[cookieName];
Another thing to add is that when I searched "AllKeys" like so:
HttpContext.Current.Request.Cookies.AllKeys
it shows an empty string array, for some reason.
any ideas?
Some possibly silly questions
Check your web-servers time and date, are they set correctly, if they are (in your case) 2 years out it will expire cookies immediately.
Check that cookieName is the same
Check that after setting the cookie to the response your not redirecting before the cookie is set. For a cookie to be set you need to set headers and push them out.
I solved it. It appears that in MVC the "return view" after the cookie creation, cause the cookie not to be saved.
How to remove all expired cookie from a CookieCollection ?
Try this.
var cookies = Request.Cookies;
foreach (HttpCookie cookie in cookies)
{
if (cookie.Expires < DateTime.Now)
{
Request.Cookies.Remove(cookie.Name);
}
}
Please note the excerpt from MSDN,
Calling the Remove method of the Cookies collection removes the cookie
from the collection on the server side, so the cookie will not be sent
to the client. However, the method does not remove the cookie from the
client if it already exists there.
You cannot directly delete a cookie on a user's computer. However, you can direct the user's browser to delete the cookie by setting the cookie's expiration date to a past date. The next time a user makes a request to a page within the domain or path that set the cookie, the browser will determine that the cookie has expired and remove it.
if (Request.Cookies["UserSettings"] != null)
{
HttpCookie myCookie = new HttpCookie("UserSettings");
myCookie.Expires = DateTime.Now.AddDays(-1);//add -1 days
Response.Cookies.Add(myCookie);
}
The way you remove a cookie is to change it expire date to some thing that has already passed.. but a expired cookie should never be sent from the browser in the first case...