Managing session cookies in Java - java

I'm working in a java web application that should not allow a user to open it in 2 different tabs, and I'm using session cookies for that. It seems to work fine in most scenarios, but the problem is that the cookies are not cleared when the browsers exits. This is how I set the cookies:
String sCookie = "mycookie=true;Path=/;Domain=.mydomain.com;HttpOnly";
if (!response.containsHeader("Set-Cookie")) {
response.setHeader("Set-Cookie", sCookie);
} else {
response.addHeader("Set-Cookie", sCookie);
}
As I understand, if I don't specify the Expires field, the cookie should be deleted on browser close. This is how I validate if the cookie exists:
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if ("mycookie".equals(cookie.getName()) && Boolean.valueOf(cookie.getValue())) {//some error}}
Is there any problem with this code? meaning, can I set the cookie with response.setHeader and then check it with request.getCookies()?
Sometimes I have problems deleting the cookie manually and then when I restart the browser the problem continues.
This is how I manually delete the cookie (on tab close):
String sCookie = "mycookie=;Path=/;Domain=.mydomain.com;HttpOnly";
if (!response.containsHeader("Set-Cookie")) {
response.setHeader("Set-Cookie", sCookie);
} else {
response.addHeader("Set-Cookie", sCookie);
}
Thanks in advance
UPDATE
This is how I create the cookie:
Cookie c = new Cookie("mycookie","true");
c.setDomain(".mydomain.com");
c.setPath("/");
c.setValue("true");
response.addCookie(c);
This is how I delete the cookie:
for (Cookie c : request.getCookies()) {
if ("mycookie".equals(c.getName())) {
c.setMaxAge(0);
c.setValue("");
}
}
But still not working. Actually, now the cookie is not deleted when I close the tab (this was working fine in my previous version with "Set-Cookie" :S).Another detail is that I'm not seeing my cookie in the Resources tab of Chrome's developer tools

As a general hint, you'd better use the response.addCookie(..) method and possibly use Cookie.setMaxAge(-1).
That said, that should be the default, so in order to understand the problem, you should use Firebug (or any browser developer tools) to inspect your cookies and check their max age. Before and after closing the browser. E.g. you may have some leftover cookie.

Actually you should set the cookies in different way:
Cookie myCookie = new Cookie(); // create your cookie
// set path, and other attributes you need
// add the cookie to the response
response.addCookie(myCookie);
Then to make a Cookie expire: :
myCookie.setMaxAge(0);
Also, in order to clean completely:
myCookie.setValue("");
myCookie.setPath("/");
So, you have to get all the cookies in the request, identify your's and clean it with something like this:
List<Cookie> cookies = request.getCookies();
for (Cookie cookie : cookies) {
// identify your cookie
if (identified) {
cookie.setMaxAge(0);
cookie.setValue("");
cookie.setPath("/");
}
}
If cookie.getName("Set-Cookie") does not match your Cookie, debug your code to see what name is assigned in the response.setHeader("Set-Cookie", sCookie);

Related

Delete specific cookies from webengine JavaFX

I would like to delete some specific HTTP only cookies generated by the JavaFX webengine.
Chrome browser allows us to delete httponly cookie which means this is programmatically possible.
I am able to delete all cookies using
java.net.CookieManager manager = new java.net.CookieManager();
manager.getCookieStore().removeAll();
Using this the user is logged out from my application as well. I want to be able to delete all cookies except the one generated for my application.
Or is it possible to delete the same cookies using javascript.
Anyone looking for the solution. Here it is.
Set this right at the start of the main method of javafx.
cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);
Then on any event(I did it onclick of a button) call this
CookieStore cookieJar = Main.cookieManager.getCookieStore();
List<HttpCookie> cookies = cookieJar.getCookies();
for (HttpCookie ck: cookies) {
if(ck.getName().equals("JSESSIONID")){
System.out.println("JSESSIONID");
}else{
ck.setMaxAge(0);
System.out.println("CookieHandler retrieved cookie: " + ck);
}
}
I hope this helps someone cause I spent the entire day looking for the solution.
According to docs getCookies()
Returns an array containing all of the Cookie objects the client sent with this request. This method returns null if no cookies were sent.
So, you should be able to iterate through the list of cookies returned and identify the elegible(s) to be deleted:
Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++) {
String name = cookies[i].getName();
String value = cookies[i].getValue();
}
If no you can override the cookie adding it with the addCookie(Cookie)

Is there a solution to keep a cookie on browser while redirect the response?

I am building a user tracking system for a web application. People could came from many urls. I want to know from which urls the came from.
I design url like this : http://www.example.com/ref/XXXXXXX.
I create a Filter to handle incoming request :
String cookieKey = "examplesite.cookie";
String cookieValue = referralIdentifier;
Cookie cookie = new Cookie(cookieKey, cookieValue);
cookie.setMaxAge(60*60*24*365);
((HttpServletResponse) response).addCookie(cookie);
HttpServletResponse resp = (HttpServletResponse)response;
resp.addCookie(cookie);
resp.sendRedirect("/");
When this code execute, I cannot see the cookie set in the browser.
If I change the redirect to forward, I can see the cookie.
The I see this blog post how to track people with cookie and redirect where the blogger suggest to use code to redirect.
So I changed my code and I replace resp.sendRedirect("/"); by
resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
resp.setHeader("Location", "http://www.example.com/");
Here I can see the cookie in Firefox but not in Chrome.
Is there a solution to track user after redirection ?
According to http://www.javamex.com/tutorials/servlets/cookies_api.shtml by default a cookie is visible to "requests to subpaths of the parent from which the cookie was set".
This might be your problem. To make the cookie visible on all paths, you can set the path to "/" using cookie.setPath("/").

Cookie set on the response doesn't show up in subsequent request to server until browser has made two new subsequent requests

An initial request is made to the server, and in the response a cookie is added:
response.addCookie(studyPrefsCookie);
On the web page, in the developer tools, I can see the cookie that was just set. Great. Here's a pic:
My assumption is that now that the cookie is set, every subsequent request to my web application (same domain, same servletcontext, etc), will now contain this cookie value in the cookies available from the request object. However, it appears that on the very next request, the cookie value is not there, even though by inspecting the request in the developer tools shows the cookie value as being sent. On the second subsequent request, it shows up normally. Here's what the request looks like, same each time from the browser:
I even tested this again by starting from scratch, and then making an ajax call after the the first page load, back to the server. First ajax call had all the right cookies as far as the browser was concerned, but the httpservletrequest object's cookies didn't have it. Making another identical ajax call, now the server found the cookie value. Is this expected behavior?
I'm reading the cookie the same way on the server side, with some helper methods:
Cookie[] cookies = studyCookieService.getCookiesByName(request.getCookies(), "STUDYPREFS");
if(cookies.length > 0 && studyCookieService.doesCookieContainValue(cookies[0], studyCookieService.getConsentNotCompletedCookieValueWithoutStudyId())){
//redirect
return "redirect:/" + STUDY_CONTROLLER_REQUEST_PATH;
--service methods
public Cookie[] getCookiesByName(Cookie[] cookies, String cookieName){
List<Cookie> matchingCookies = new ArrayList<Cookie>();
if (cookies != null) {
for (Cookie ck : cookies) {
if (cookieName.equals(ck.getName())) {
matchingCookies.add(ck);
}
}
}
return matchingCookies.toArray(new Cookie[matchingCookies.size()]);
}

In Java servlet, cookie.getMaxAge() always returns -1

If I set a cookie with a setMaxAge() well into the future, when I read the cookie back into memory in a subsequent request, the getMaxAge() gives me back a -1. I have checked the actual cookie via Chrome's settings, and inspector, and I can verify that the expiration date is indeed set 60 days in the future.
static public void setHttpCookie(HttpServletResponse response, String payload) {
Cookie c = new Cookie(COOKIE_NAME, payload);
c.setMaxAge(60*86400); // expire sixty days in the future
c.setPath("/"); // this cookie is good everywhere on the site
response.addCookie(c);
}
static public String checkForCookie(HttpServletRequest req) {
Cookie[] cookies = req.getCookies();
if ( cookies != null ) {
for ( Cookie c : cookies ) {
if ( COOKIE_NAME.equals(c.getName()) ) {
int maxAge = c.getMaxAge();
logger.debug("Read back cookie and it had maxAge of {}.", maxAge);
String payload = c.getValue();
return payload;
}
}
}
return null;
}
Why does c.getMaxAge() always return -1?
The browser does not send cookie attributes like path and age back. It only sends the name and the value back. If the max age is expired, then the browser won't send the cookie anyway. If the path is not covered by request URI, then the browser won't send the cookie anyway.
If you really need to determine the cookie's age after you have set the cookie, then you should remember it yourself elsewhere at the moment you've set the cookie, such as in a database table, associated with the logged-in user and cookie name, for example.
This problem is unrelated to the Java/Servlets. It's just how HTTP cookie is specified. You'd have exactly the same problem in other web programming languages. See also the following extract from Wikipedia (emphasis mine).
Cookie attributes
Besides the name–value pair, servers can also set these cookie attributes: a cookie domain, a path, expiration time or maximum age, Secure flag and HttpOnly flag. Browsers will not send cookie attributes back to the server. They will only send the cookie’s name-value pair. Cookie attributes are used by browsers to determine when to delete a cookie, block a cookie or whether to send a cookie (name-value pair) to the servers.
The best what you can possibly do is to bump the cookie's max age every time during e.g. login. You can easily achieve this by setting exactly the same cookie once more (especially exactly the same domain/path/name). It will overwrite the existing cookie. This is usually done that way on so-called "Remember me" cookies.

Update domain of existing cookie

I have a site name www.goo.com and i used to save cookie without declaring domain name when creating the cookie.
Now, i want to add sub domain foo.goo.com
I save the cookie in the domain and not in the sub domain.
There are 2 problems:
I want to delete the old cookie.
I tried to do 'cookie.setMaxAge(0)' already and the problem is that in Firefox and chrome it do not work. it work only in IE.
why? and what i can do about it?
When i do
Cookie[] cookie = request.getCookies();
if (cookie != null) {
for (int i = 0; i < cookie .length; i++) {
cookie[i].getDomain(); //here i get null.why?
}
}
Why i get null in the getDomain() line?
Edit:
i tried to add this line:
response.setContentType("text/html");
to send the content type.
I also tried to send the cookie through the response.
Someone have another idea, for the 2 problems the presents here?
Answered here: How do you remove a Cookie in a Java Servlet (you need to send a text/html content type)
When a client sends cookies to the server, it only sends the name/value. The other fields are only available when setting the cookie.

Categories