7

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?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
broc.seib
  • 21,643
  • 8
  • 63
  • 62
  • please check this: http://stackoverflow.com/questions/177708/cookie-getmaxage – Hui Zheng Jan 18 '13 at 03:03
  • Try to declare the long for setMaxAge prior to using it (just try), because it will only return -1 if the cookie was set to be destroyed whenever the browser shuts down (which mean a negative number would have to be placed within setMaxAge to begin with). I am not sure though since I have not done this myself, though this is what it seems to be to me when reading the Java documentation. – John Mikael Gundersen Jan 18 '13 at 03:11
  • @BalusC: If you say so, was only a suggestion :) – John Mikael Gundersen Jan 18 '13 at 04:32
  • @HuiZheng thanks... I swear I searched StackOverflow before posting! :-) – broc.seib Jan 19 '13 at 13:43

1 Answers1

15

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    I allow user to toggle the length of their session, i.e. "remember me", and I wanted to read which maxAge was previously set on the cookie. I will simply add the info I need to the payload of the cookie. Thanks for posting the wikipedia reference, which I should have found. – broc.seib Jan 19 '13 at 13:41
  • If you're trying to (re)invent "Remember Me", then you should surely have a DB table with therein the unique autogenerated cookie value associated with the user ID. Just store the last set maxage in a new column of the same table. – BalusC Jan 19 '13 at 13:44
  • Yes I am (re)implementing this widely known feature. Specifically I am implementing a "remember me on this computer", in which case a state of SHORT_SESSION or LONG_SESSION is stored in the cookie itself, such that the preference is set per device. – broc.seib Jan 19 '13 at 21:24
  • Then you may find this answer helpful, http://stackoverflow.com/questions/2185951/java-how-do-i-keep-a-user-logged-into-my-site-for-months/2186072#2186072 In Java you can use `java.util.UUID` to generate an UUID. – BalusC Jan 19 '13 at 21:26
  • Thanks for the pointer. That is precisely the pattern I had been using -- a "remember me id" column in the user table, and two cookies, one for remember me and the other representing the session. Today, my implementation uses a single cookie for the session, and toggles whether it is LONG or SHORT. This evolution has made the code much simpler and concise, and no call to the database. Use of UUID would have simplified my doing a hash of some random stuff to generate my id. – broc.seib Jan 20 '13 at 16:09