Suppose in my Java app I do
Cookie myCookie = new Cookie("myCookie", "someValue");
myCookie.setMaxAge(3); // 3-seconds
When a cookie is sent in the response it must have an Expiration Date. My understanding is it will expire on CreationDate + 3 sec (maxAge). maxAge is the delta.
If I create a cookie at 1/1/2020 16:08:00, is its Expiration Date 1/1/2020 16:08:03 ?
Then who sets the original Creation Timestamp of the cookie, is it the constructor? How is the overall date tracked?
The cookie creation time is not stored in the cookie. The client keeps the cookie for the given time, starting when it receives the cookie.
In addition to what #JB Nizet said, clients can also update any cookie-related information it receives from the server's Set-Cookie response header.
Test it yourself in Chrome's Dev Tools, "Application" tab, there's a "Cookies" node in the left panel. For every domain, it allows you to see and/or modify any cookies you have stored in your browser. If you choose to update the "Expires/Max-Age" to a date in the past, the browser will automatically remove that cookie. You can also update it to sometime further out in the future.
Therefore, it's ultimately up to the server to know if a cookie is actually "valid." You should never rely on the max-age/expires data coming from the client to determine true validity. Clients use this to simply know when to delete it from it's local storage.
Related
I have a java web application. I implemented a login system, with user rights a while ago, and included a "remember-me" functionality with unique string ID's saved client side in cookies.
This has worked ok, except for the fact that the remember me functionality always fails on first page load whenever a new session starts. However, since most users access a non-restricted page first, complaints has been absent. Nonetheless, I'd like to fix it. Here is what I have learned.
I use implementations of javax.servlet.Filter to check if a user has rights to se a page. for example baseURL/pages/admin/*. Filter interface has a method called doFilter, which accepts a ServletRequest, and ServletResponse object as parameters. I cast these to HttpServletRequest and HttpServletResponse. The HttpServletRequest gives me access to cookies and session.
If i iterate through the cookies, I find my "remember"-cookie, with the unique ID as a value. However, this ID is wrong.
Now, in my Servlet class, which follows the front controller pattern, I also have a check for user logged in, and remember me. But because this is executed after the filter, it is not sufficient to check only here. Still, I do want to check for every page, even if it is not restricted, as it changes the layout slightly if you are logged in.
The java HttpServlet service method accepts a HttpServletRequest and HttpServletResponse object. In other words, no need for casting here. Funny thing is though, If i try to access my cookies from here, it will give me an identical id for the session cookie, but a completely different uid for my "remember"-cookie.
I have found that my system adds new remember cookies for each of my filters. And if I try to access a page in the admin path, both cookies from /webapp/pages, and cookie from /webapp/pages/admin will be present in chrome inspector. When accessing the cookies in the filter, the /webapp/pages/admin is the only one that will exist. Oppositely, the /webapp/pages is the only one that will exist in the front controller servlet service method.
I guess this is because of the mapping of said filter and servlet, which matches the path of the cookie. The problem is that I never intended there to be cookies stored hierarchically, and only want the one to be stored, at /webapp/pages. My system has now stored plenty of these deeper pathed cookies all over my client network, and whenever a user logs in and out, they might get out of sync with a new uid.
Is there a way I can force retrieving the /webapp/pages cookie over the /webapp/pages/admin cookie? Or is there a way to retrieve both? I could just check both uid's for a match if I can manage that (hence the title of my question)
For the future, I have made sure to set the path of cookie storage, so that the same path will be used, but as the cookies has a year to expire, this will not solve my problems for a long time, unless I find a way to check the correct cookie.
The answer to the title question is; you can't.
The browser will decide which cookies it deems most relevant, and there is nothing you can do to change that. When your filter is mapped to a subpath, and servlet is mapped to a higher path, you will get the best matching cookie for each path.
The specific problem in the question text is caused by a bad coding pattern. The remember me cookies should be stored at a specific path when created, in this case /webapp/pages. This will prevent the cookie from being created as multiples, in hierarchical paths.
There is still the problem of already existing cookies client side. These can be handled by adding the following javascript in a central area of your code, somewhere where you'd know that all users will encounter it:
document.cookie = 'remember=; path=/webapp/pages/user; expires=' + new Date(0).toUTCString();
document.cookie = 'remember=; path=/webapp/pages/admin; expires=' + new Date(0).toUTCString();
This will set the unwanted cookies to expire at an already past date, effectively deleting it.
Now only one cookie with name "remember" will exist for the domain, and both servlet and filters will fetch the same cookie, regardless of their mapped subpaths.
I have an application using Spring Boot where I set a HttpOnly cookie. In the browser I can inspect it and see that it's well set as HttpOnly. With this I avoid the client side from using javascript on it.
But, do I have to do anything on the server side when reading the cookie? As far as I understand, I cannot use javascript to read the cookie but I can still create a non HttpOnly cookie with the same name and value as the HttpOnly one just using a browser plugin. On the server side, wouldn't I need to verify the cookie and whether it's HttpOnly?
I've tried doing that by just getting the list of cookies from the request but it seems all of them have the different fields set to a default value. The only fields I can read are the name and the value of the cookie.
Is this the expected behaviour?
This is, indeed, the specified behaviour.
The Set-Cookie Header transmits information like HttpOnly to a client. But a call from the client to the server uses the Cookie header, which only includes cookie names and values (but no further information). Therefore, the server cannot derive this information from the Cookie header alone. It is simply not there.
This is specified in RFC 6265 „HTTP State Management Mechanism“ in Section 5.4 „The Cookie Header“:
4. Serialize the cookie-list into a cookie-string by processing each
cookie in the cookie-list in order:
1. Output the cookie's name, the %x3D ("=") character, and the
cookie's value.
2. If there is an unprocessed cookie in the cookie-list, output
the characters %x3B and %x20 ("; ").
Since the information is missing, it is often set to a default value.
I'm new to Java. I'm writing an application to link to a vendors Flash site. I have my BlazeDs based program talking to their site. I'm running into a problem where a session cookie is not getting set. The problem is that the host doesn't return it as a "set-cookie" header.
Their site returns the following cookieDirectives to set the SMSESSION cookie
cookieDirectives
Externalized Object
flex.messaging.io.ArrayCollection
[0] String SMSESSION={CONTENT STRIPPED FOR CLARITY}; max-age=-1;path=/; domain=.-----.com
I can set the cookie in my amfConnection as follows:
amfConnection.addHttpRequestHeader("Cookie", resultString);
However, that only gives me the one cookie and there are several others I need. The others have been set earlier by the host and are set using a "Set-Cookie" header.
How can I either add this cookie to the existing ones or recover the existing cookies so I can manually add them.
I was able to resolve this by changing my approach. Instead of relying on my amfConnection to handle the cookies I grab the session id using httpclient, store it in a variable, and then push my cookies to amfConnection.
For one of our requirements I am talking between two servers using HTTP protocol. The interaction is long running, where a user might not interact with the other site for pretty long intervals.
When they come to the page, the log in into the remote site. Every time user tried to interact with the remote site, internally I make a HTTP call (authetication is done based on sessionId).
I was wondering if there is a way to also refresh the session and ensure that it does not expire.
As per my limited understanding, browser handles this by passing keep-alive in header or cookie (which I don't understand completely). Can anyone suggest a programmatic way in Java to achieve keep-alive behavior
1.
<session-config>
<session-timeout>-1</session-timeout>
</session-config>
Simply paste this piece if code in your deployment descriptor (DD).
If you want to keep your session alive for a particular duration of time replace -1 with any positive numeric value.
Time specified here is in minutes.
2.
If you want to change session timeout value for a particular session instance without affecting the timeout length of any other session in the application :
session.setMaxInactiveInterval(30*60);
**********************
Note :
1.In DD, the time specified is in minutes.
2.If you do it programatically, the time specified is in seconds.
Hope this helps :)
I guess below code can help you, if you can pass JSESSIONID cookie then your container will take responsibility to keep the session alive if its same session that might be created from some other browser.
find the link below that explained a lot.
Click Here
Code snippet from the link above
BasicCookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "97E3D1012B3802114FA0A844EDE7B2ED");
cookie.setDomain("localhost");
cookie.setPath("/CookieTest");
cookieStore.addCookie(cookie);
HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();
final HttpGet request = new HttpGet("http://localhost:1234/CookieTest/CookieTester");
HttpResponse response = client.execute(request);
Take a look of Apache HttpClient and see its tutorial. HttpClient supports keep alive headers and other features that should enable you to programmatically make an HTTP call.
I need to implement a simple remember me option in a java servlet with cookies, without using any advanced framework.
First, at login, I create the cookie and send it in response to the browser (client). The value to be stored in the cookie is just a simple hash from username + password.
How should I manage the incoming request from the browser, sending the cookie?
My approach is to check between registered users if there is any user that has the hash from username + password equal to the value in the cookie?
Is this approach correct?
Also, I did not understand exactly what is the mechanism of the expiration date. Does the browser delete the cookie when it is expired, it not, how do I check if the cookie is expired?
As long as you're not using HTTPS the method you suggest is highly insecure. I would suggest to generate some sort of session token (e.g. use java.util.UUID.randomUUID()) and set this as cookie and store it somewhere on the server side so you later can identify the user associated with this session id in the cookie.
This gives you the opportunity to reset a certain session cookie if you think there's some fraud happening and there's no direct relation between the user name/password and the cookie id you use. But note: this method is still vulnerable to a man-in-the-middle attack.
Concerning the expiration: yes the cookie becomes invalid and might get deleted by the browser if it is expired. But you can set the cookie to something in the year 3000, so it lives forever.