I'm writing a small webserver in Java, using HttpCore for most Http requests/responses etc.
Now I would like to be able to create, store and load cookies. I can't find anything in HttpCore and I'm not that familiar with other libraries. Is there an exisiting library (preferably with a working example) to handle cookies?
Edit: I see I was a bit confused regarding the usage of cookies. I'm not completely sure how it works, but I want to keep a session, and to access session variables from the web server. How can I do this? If the browser saves cookies, does it send them to the server? How do I access them?
Session support in a server, is typically built using an object store. A simple object store would be a Map or a Set. The objects in this store ( the values in the case of the Map) have a one-to-one mapping with the concept of a logical session, i.e. for each session created by the server, there will be one item in the store.
Sessions managed by the store may allow for attributes to be associated with them. The list of such attributes may not be known before hand, so you'll need another map for this purpose; the keys would be the attribute names, and the values would be attribute values.
As far as management of the session store is concerned, you'll need to create a new Session in the store, when an API call is made to your server. In simpler words, if a web application decides that it needs to create a session, the server's API must provide the necessary interface to do so. Creating the session object alone is not enough; you'll also need to write the session ID out as a cookie when you first create the session. The API must allow for writing the appropriate response in such a case. You might want to take a look at the Servlet API, specifically for the HttpServletRequest and HttpSession classes, and a servlet container implementation for this purpose.
On the topic of accessing cookies from a request, you'll need to parse the incoming HTTP request headers to check for any cookies sent by the browser. Browsers and other HTTP clients are expected to use the Set-Cookie request header for this purpose. You'll need to ensure that a session object may be returned to the web application only when a valid cookie is supplied in the request.
Related
I am working on Spring 4 mvc application with mysql database, tomcat server.
Basically, I am creating a Spring rest which will be used by Angular JS.
Note: I am not using Spring security
In order to avoid session replication in case of clustered environment, I am using cookie approach.On login, I am generating one unique session id (using java UUID) and use it to create a cookie and then set the cookie in the response.Also, storing that session id in database along with any user data.
In order to authenticate every rest API, I have written a Spring interceptor which will intercept every rest API call which in turn check if there is a cookie in the request.If it is present, I am fetching session id value and using it, making a database call to check if it is valid or not. On logout, I am deleting the cookie.
Base on what i am doing as explained above, I have few questions:
1) Is my approach correct? or do you see any flaw in it.
2) Let me know if there is any other better method to achieve the same i.e. to avoid session replication.
3) Since, I am not using any HTTP session, how do I achieve something like session-timeout or do i even need it?
1) Is my approach correct? or do you see any flaw in it.
Its a good approach. Just a couple of points though in order of precedence:-
If you are using your API to service alot of requests then think about using in-memory cache rather then DB. Going to DB is relatively much more expensive. Alot is subjective I know and it depends on your setup, but just consider the DB for data you want to live beyond sessions. Better to use a more temporary/faster store such as an in-memory cache for things like API tokens. If across a cluster then explore a distributed cache solution.
Using cookies is not necessarily a security risk but have a bit of a read about CSRF. More secure to pass the token in a HTTP Header rather than in the cookie itself - that is if you are concerned about CSRF (I do use the Header approach in my own apps but I think CSRF is relatively rare and it depends on how sensitive your data is)
2) Let me know if there is any other better method to achieve the same
i.e. to avoid session replication.
Nothing to add over response to 1.)
3) Since, I am not using any HTTP session, how do I achieve something like session-timeout or do i even need it?
Store (preferably in cache) a timestamp with the token, and refresh it in the cache for each transaction that uses the token. Then, when checking if you consider if the token is valid, check the timestamp and you can decide (based on time elapsed) if you wish to remove the token and request the client to re-authenticate.
So, I'm in the middle of building an application where I want the user to be able to send a link to another user and work on the same data. There is little need to persist the data for more than 15 minutes and I want the application to not have to rely on a database.
I have a few variables which I am currently storing in a HttpSession.
Ideally I'd like to be able to set a parameter "sid" in the URL, and use that to set the session ID on the second client's browser - the one that's received a link with the SID.
Unfortunately, there seems to be no way to change the SID of a current session once it's been set up.
The only solution I've come up with so far is referring to the doGet() with a HttpPost.setHeader("Cookie", "JSESSIONID="+ getSessionId()) method, and getting the data with a specific session that way, but this seems pretty clunky.
Any suggestions?
EDIT
This has seemingly turned into a discussion about the wisdom of setting two users up to have the same session so session vars may be kept the same. Note that a non-db, ie light weight solution was what I was looking for. PHP allows you to arbitrarily set a session ID to do this, but I'm deploying to Tomcat in this instance. Something which allows lightweight sharing of a few parameters, that's it...
What I've done, then, is to set context vars using context.setAttribute(). Ugly as sin, but all I can come up with, unless anyone has any better ideas.
This approach has some security issues because you are simulating [session hijacking] with it 1:
In computer science, session hijacking, sometimes also known as cookie
hijacking is the exploitation of a valid computer session—sometimes
also called a session key—to gain unauthorized access to information
or services in a computer system. In particular, it is used to refer
to the theft of a magic cookie used to authenticate a user to a remote
server. It has particular relevance to web developers, as the HTTP
cookies used to maintain a session on many web sites can be easily
stolen by an attacker using an intermediary computer or with access to
the saved cookies on the victim's computer (see HTTP cookie theft).
Better approach is to set your data in a way that both users can approach it from their sessions. If you are using single server you can do that with some global data within a server. In clustered or cloud environments you'll need some common storage for that (ie. database, global cache, etc.)
EDIT
You are on a right track to share data among two users with different sessions.
There is one context per "web application" per Java Virtual Machine
where an attribute allows a servlet container to give the servlet
additional information.
Attributes are meant to be used to share data inside container among servlets of the same web application.
For clusters:
In the case of a web application marked "distributed" in its
deployment descriptor, there will be one context instance for each
virtual machine. In this situation, the context cannot be used as a
location to share global information (because the information won't be
truly global). Use an external resource like a database instead.
Here's my situation, I have a web site that I just load using Apache HTTPD that then makes Ajax POST requests to a servlet which returns only JSON data. That JSON data is then used to update tables, etc..
Now I want to add user logic to my site, and also maintain servlet sessions for requests made by individual users.
I understand that the servlet needs to return the session id generated by the first call to request.getSession(), so that the client can add this sessionid to future Ajax requests in order for the servlet to know which session in memory to use.
I also understand that the two ways that this session id can be returned to the client is either using cookies (JESSIONID) or URL Rewriting.
If I can't use URL Rewriting, because I'm just returning JSON data, are cookies the only way I have left to send back the session id to the client?
Also, as a side question, currently I noticed that there is no JSESSIONID cookie in any of my HTTP responses from the servlet. Someone suggested to me that this was something new in Tomcat7 and that I had to activate them in the global context.xml. Does this mean that by default there is no session handling even if you make calls to request.getSession() ?
You have correctly identified two of the three ways of handling session IDs supported by Tomcat. There is a third way to track sessions but only if the application runs over SSL. In that case you can configure Tomcat to use the SSL session ID.
If the Servlet calls request.getSession() then Tomcat always includes a session ID in the response. However, those cookies are marked as httpOnly by default in Tomcat 7 onwards which means they are not visible to javascript (to protect against XSS attacks that try to steal the cookie). If the session cookies need to be visible to script then you need to set useHttpOnly="false" in either the web application's context.xml (to change the default for just that file) or in $CATALINA_BASE/conf/context.xml to change the default setting for every web application.
I am new to web app development.
Basically, I have got a GWT based web app. A user first needs to login. After successfully authenticated himself, he will be taken to the second page (actually another GWT view in the same page).
The login will generate a pair of keys from another web service. These key will be used for future communication with the web service, it is like:
client -> server => web service
Now the problem comes, I cannot save the key pair in a database. What shall I do?
I have been told I can put the key in a cookie and send back to the client. Every time the client raise request the cookie will be sent to the server.
I have also been told to set the keys as the session key and send them to the client.
I am note quite sure what is the different between these two methods. Are they applicable? or secure?
Many thanks
Both methods are applicable. The first one (using cookies) will rely on the user side (its cache). Second one, will keep data on server side (session). As a rule (although it's arguable), you never trust the client. What if client made a clear cache to his browser.
Even for security (I am not an expert here), I think storing data on server is always safer.
You can use both cookie as well as session or a combination of both to achieve this. Cookie are usually created when you launch your application (Also you can create it as and when required). The disadvantage of this is, it is temporary. As soon as you clear the cache or cookies, whatever cookie you created will be removed. If you store it on server side i.e., in session you must make sure to create a separate key value pair for each set of user, as many users can connect to the same server. The best approach will be using both the option together. I.e., to save a cookie and validate the session id.
This link will help you understand how create a cookie and session.
Best way managing session in Java. I heard that cookies are not reliable option for this as they gets stored into browser and can be accessed later on? Is this correct? If possible please come up with the answers with the coding example.
Which is the best among:
URL Rewriting: Server will add an additional parameter at the end of URL link
Hidden parameter in Form: server will add an additional parameter at every form in HTML
cookie: Server will ask browser to maintain a cookie.
The session management (client identification, cookie handling, saving session scoped data and so on) is basically already done by the appserver itself. You don't need to worry about it at all. You can just set/get Java objects in the session by HttpSession#setAttribute() and #getAttribute(). Only thing what you really need to take care of is the URL rewriting for the case that the client doesn't support cookies. It will then append a jsessionid identifier to the URL. In the JSP you can use the JSTL's c:url for this. In the Servlet you can use HttpServletResponse#encodeURL() for this. This way the server can identify the client by reading the new request URL.
Your new question shall probably be "But how are cookies related to this? How does the server do it all?". Well, the answer is this: if the server receives a request from a client and the server side code (your code) is trying to get the HttpSession by HttpServletRequest#getSession() while there's no one created yet (first request in a fresh session), the server will create a new one itself. The server will generate a long, unique and hard-to-guess ID (the one which you can get by HttpSession#getId()) and set this ID as a value of the cookie with the name jsessionid. Under the hood the server uses HttpServletResponse#addCookie() for this. Finally the server will store all sessions in some kind of Map with the session ID as key and the HttpSession as value.
According to the HTTP cookie spec the client is required to send the same cookies back in the headers of the subsequent request. Under the hood the server will search for the jsessionid cookie by HttpServletRequest#getCookies() and determine its value. This way the server is able to obtain the associated HttpSession and give it back by every call on HttpServletRequest#getSession().
To the point: the only thing which is stored in the client side is the session ID (in flavor of a cookie) and the HttpSession object (including all of its attributes) is stored in the server side (in Java's memory). You don't need to worry about session management youself and you also don't need to worry about the security.
See also:
Authenticating the username, password by using filters in Java (contacting with database)
How to redirect to Login page when Session is expired in Java web application?
How to implement "Stay Logged In" when user login in to the web application
All Java web frameworks support cookies or URL-encoded session IDs. They will chose the correct approach automatically, so there is nothing you need to do. Just request the session object from your container and it will handle the details.
[EDIT] There are two options: Cookies and a special URL. There are problems with both approaches. For example, if you encode the session in an URL, people can try to pass the session on (by putting the URL into a mail, for example). If you want to understand this, read a couple of articles about security and build app servers. Otherwise: Your Java app server will do the right thing for you. Don't think about it.
The cookie just stores the session ID, this ID is useless once the session has expired.
Servlet specification defines the API for accessing/setting session data in standard J2EE application. Also it defines that session data is stored on the server-side and nothing is transferred to the client except the session identifier. There are 2 mechanisms how session id is transferred:
1) request URL e.g. jessionid=....
2) cookie
Mechanism is determined automatically based on client capabilities.
EDIT. There is no best option, there is servlet specification that defines the way.
Http is a stateless, client-side pull only protocol.
To implement a stateful conversation over it, Java EE Web Server need to hide some information (which is sessionid) in client-side and the mechanism it can use should follow HTTP and HTML spec.
There are three ways to accomplish this goal:
URL Rewriting: Server will add an additional parameter at the end of URL link.
Hidden parameter in Form: server will add an additional parameter at every form in HTML.
cookie: Server will ask browser to maintain a cookie.
Basically, modern web server will have a "filter" to choose which way to use automatically.
So if Server detected that browser already turn off cookie support, it will switch to other ways.
2 important questions:
Which web technology are you using? JSF, Struts, SpringMVC or just plain servlets/JSPs.
Servlets/JSPs already give you the session support you need. JSP Example: Hello, <%= session.getAttribute( "theName" ) %>
I really don't think you have something to worry about cookies, since the data is stored safely in the server and handeling the cookie is done automaticlly.
Is your application installed on a single server?
If YES than you have no problem, use the servlet session option.
if NO than you gotta find another way to do this. Like using a sticky session, or maybe parse the entire session object in the requests/responses as a field. This option indeed requires you to take security measures.