Java web app security: adding tokens to requests - java

I'm looking for a method or current API that allows you to add on tokens to web app requests.
Maybe within the session but not persisted.
Or if you could help me by outlining an efficient method for doing this
E.g.
1. GET request => Servlet generates a token and prints it in the view
2. returns a view with a hidden token
<input type="hidden" name="token" value="UA37jdjs9UDJS3">
<input type="submit" name="deleteEmail" value="Delete">
3. POST request => form is submitted and checks if the token is the same.
Few things to note, If there are Ajax requests then some other tokens would have to be alive for a number of requests.
If the user decides to close the browser, the token would have to die when the session
is timed-out.
If the user fails to complete the form, goes off to do something else on the site,
those tokens would have to be deleted as they go unused.
But what is the best way of implementing a system like this,
Does Spring Security 3 have a system that i can use?
within the Java,Grails,Spring MVC, Spring Security 3 and Hibernate area

Have a look at the HDIV project at http://www.hdiv.org/. They do exactly this. Even if you don't use the HDIV project's code then the information there may give you an option how to do it yourself. It was a good primer for me to learn about handling tokens for things like CSRF and other uses like double submit controls.

Did you take a look at "Synchronizer Token Pattern" in the Grails documentation at http://grails.org/doc/1.2.0/guide/single.html ?

First thought was that you might just use the already generated session id. But if you are trying to fork state I would suggest to use something like seams conversation model

Why don't just uses the session_id that the Web container generates for you when you call request.getSession()?
If you want to create your own "token" you might want to check Cookies.
A Cookie is a key-value pair sent as an HTTP header by a web server to a web browser and then sent back unchanged by the browser each time it accesses that server.
To create a cookie in a Servlet you can uses:
public void doGet ( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException {
// Create a cookie
Cookie c1 = new Cookie("yourdomain.token","the value");
response.addCookie(c1);
//build your response
}
The cookie will be automatically included in the next http request. You can read it back with:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
//build your response
}

I recently encountered a use case for this.
If an old application window was present in the browser, and a login link was clicked from another browser window, the login action first created a new session, and then redirected to the application window. This triggered the old window's onunload method method, which resulted in a logout request to the server logging out the new user.
Relying on a javascript onunload event for logging out seems kind of crappy to me, but this could not be changed, so we chose to do as the OP suggested and added a token in each rendered view, checking it for each request. This stops the onunload logout request from terminating the new session.
As to the best way, I would say this is pretty straightforward. You can for instance use http://java.sun.com/j2se/1.5.0/docs/api/java/util/UUID.html to generate unique keys. If you are using a component-based framework like Tapestry, JSF or Wicket there might be a more high-level way of handling this.
Is this similar to your usecase? Or are you trying to achieve something completely different?

Related

Managing session and request attributes in Servlet

I have a very simple JSP page where it has one search box and based off the input, in the search box, it will return a response with a submit button to get the following response.
I noticed that whenever I use request.getattribute("foo") in my servlet to retrieve some request it returns null due to the request ending so I looked at the answers on here and started using session.getattribute("foo") instead. However, now I am stuck having session variables responses being set and it is causing my view to have old session data that isn't suppose to be there so now I have to use session.removeAttribute("foo"), whenever, I don't want that particular response data to be shown.
Is there a better way to go about managing this instead of having to use session.getattribute("foo"), session.removeAttribute("foo") and session.setattribute("foo")?
You should work with request.getSession()
Returns the current session associated with this request, or if the request does not have a session, creates one.
Set an attribute:
request.getSession().setAttribute("foo")
And get attribute using:
request.getSession().getAttribute("foo")
It will be used in the context of the request and not effect other requests, so you don't need to remove attribute.
Read more in Servlets tutorial
Servlets provide an outstanding technical solution: the HttpSession API. This is a high-level interface that allows the server to "remember" a set of information relevant to a particular user's on-going transaction, so that it can retrieve this information to handle any future requests from the same user.
You can go for request.getparameter("foo") or request.setparameter("foo", obj)
This can be used for every request, and it will not add to your session variables and basically will not make your "session object heavy".
Java doc:
Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.

Confusion about how java web session handeling works. Demystifying Cookies and Header differences using servlet api and HttpSession object

I am learning Spring security and Spring MVC, but I realized I needed to learn jsp Servlets first and general web programming in a java environment.
I have confusions surrounding the HttpServletRequest and HttpServletResponse objects and how they can be used to add headers to the request and response objects and how they relate to sessions.
As far as I understand, a cookie is a type of header just like Content-type and Accept.
The java servlet api just makes it easy to work with the header by using methods specific to the context in which the header is being used. For example:
response.setContentType(String mimeType)
response.setContentLength(int lengthInBytes)
My confusion starts here.. Cookie is not a String or int, its a object:
response.addCookie(Cookie cookie)
response.getCookies()
Since a cookie is a type of header, can't I just use something like this:
String cookieVal = response.getHeader("cookie")
I'm having difficulty understanding session management and how it relates to the HttpServletRequest and HttpServletResponse API.. What is the HttpSession object for?
HttpSession.getAttribute() // What is this getting??
HttpSession.setAttribute("Bla Bla", "valuetoset") // What is this setting?
You can read the RFC describing Cookies and the related headers, Set-Cookie and Cookie to understand what they are.
You can go through Chapter 7 of the Servlet Specification if you want to understand in detail how Cookies and Sessions are related.
You first need to understand that HTTP is a stateless protocol. This means that each request that a client makes has no relation to any previous or future requests. However, as users, we very much want some state when interacting with a web application. A bank application, for example, only wants you to be able to see and manage your transactions. A music streaming website might want to recommend some good beats based on what you've already heard.
To achieve this, the Cookie and Session concepts were introduced. Cookies are key-value pairs, but with a specific format (see the links). Sessions are server-side entities that store information (in memory or persisted) that spans multiple requests/responses between the server and the client.
The Servlet HTTP session uses a cookie with the name JSESSIONID and a value that identifies the session.
The Servlet container keeps a map (YMMV) of HttpSession objects and these identifiers. When a client first makes a request, the server creates an HttpSession object with a unique identifier and stores it in its map. It then adds a Set-Cookie header in the response. It sets the cookie's name to JSESSIONID and its value to the identifier it just created.
This is the most basic Cookie that a server uses. You can set any number of them with any information you wish. The Servlet API makes that a little simpler for you with the HttpServletResponse#addCookie(Cookie) method but you could do it yourself with the HttpServletResponse#addHeader(String, String) method.
The client receives these cookies and can store them somewhere, typically in a text file. When sending a new request to the server, it can use that cookie in the request's Cookie header to notify the server that it might have done a previous request.
When the Servlet container receives the request, it extracts the Cookie header value and tries to retrieve an HttpSession object from its map by using the key in the JSESSIONID cookie. This HttpSession object is then attached to the HttpServletRequest object that the Servlet container creates and passes to your Servlet. You can use the setAttribute(String, Object) and getAttribute(String) methods to manage state.
You are correct that cookies are managed using headers. There are TWO cookie management related headers: Cookie and Set-Cookie.
Cookie header is sent by the user agent (browser) and will be available in your HttpServletRequest object and the Set-Cookie header is appended to your HttpServletResponse object when you use methods such as addCookie(Cookie).
In Java an HttpSession is established when the first request reaches your application. The Servlet Spec implementation in your container (Jetty, Tomcat, WebSphere, etc) will create and manage the HttpSession. The browser will receive a JSESSIONID cookie which will identify this particular session in the future.
Agreeing with the answers given above, I would like to conclude that Cookie and Session are two different entities in the world of web.
Cookie
Cookie represents some brief information that's generated by server and stored on client(browser). According to HTTP mechanism, browser have to send all the cookies(that have not expired), that server had sent before to browser.
Session
HTTP is a stateless protocol. Unlike FTP and other protocol, where connection state is preserved between multiple request-response transaction, in HTTP connection is established for one request and it's closed when response for that request is satisfied. This flaw in HTTP is present, because it was designed in early days to serve static web pages only. But as web has expanded, it's now used to serve dynamic full-fledged webapps. Thus, it has become necessary to identify users. Thus, for every request served by web-server, a labeling mechanism is required which can identify user of each request. This identification of user of request(whether the request has came from same user, same machine), sessions are used.
Session can be successfully implemented only if web-server can receive any information about the user in the request. One way of making this information available to user is Cookie. Others are URL rewriting, hidden fields, etc.
session.setAttribute() will store information in current session on server side not on client side(browser).
Hope it may help you.
Ok Looks like you want to see the difference between Cookies and Headers. They have different purpose. Cookies are temporary storage of information on client side. Server set the cookies(data) on the response and once set browser send these cookies(data) with each subsequent requests till the cookie expires. But headers are used as hints to browser and server. For ex
setHeader("Content-Type", "application/json");
will inform client to prepare to see a json response in the payload. Since it is a "one time" information there is not need the browser to send that information back to the server with each new requests like cookies.

Best strategy to handle page navigation in JSP

I am exploring JSP to implement dynamic web pages. One issue to solve is navigation between pages. Users have the possibility to go back and forward in their browsers.
This has to be handled. If someone logs out (for example), we don't want someone else to retrieve the session or data by clicking 'go back'. Another example is that we don't want to resubmit forms twice.
I am looking for tips and advices to solve page navigation issues. I would like to create a list of issues one has to take care of + possible solutions:
Issues:
Making sure sessions cannot be retrieved/hijacked with go back/forward clicks
Making sure forms and not submitted twice
Making sure users cannot fiddle cookies or URL data or hidden fields to break control flow and security
Solutions:
Implement a stack of visited pages
When a page is invoked, register the moment it is displayed to differentiate new requests from 'go back'
Control current session
P.S.: I have seen this question, but there is no real answer to it.
Making sure sessions cannot be retrieved/hijacked with go back/forward clicks
Just disable browser cache of those pages. See also Prevent user from seeing previously visited secured page after logout.
Making sure forms and not submitted twice
Generate a long, unique and impossible-to-guess string, store it in both the session ..
String token = UUID.randomUUID().toString();
((Set<String>) session.getAttribute("tokens")).add(token);
request.setAttribute("token", token);
request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
.. and as a hidden input field of the form.
<input type="hidden" name="token" value="${token}" />
Upon submit, compare and remove the key in the session. If it was in the session, then proceed with submit.
if (((Set<String>) session.getAttribute("tokens")).remove(request.getParameter("token")) {
// Valid token. Proceed with submit.
} else {
// Invalid token. Possible double submit.
}
Making sure users cannot fiddle cookies or URL data or hidden fields to break control flow and security
Just write robust code yourself or use an existing and robust MVC framework like JSF2, Spring-MVC, Struts2, etc.
Solutions:
Implement a stack of visited pages
When a page is invoked, register the moment it is displayed to differentiate new requests from 'go back'
Control current session
Cumbersome.
To prevent double submission, I will use an example Apache Struts 1 used by using HttpSession.
What Struts did was to generate a random token that is stored in a session and added in a form page in a presentation layer (JSP). When a user submit a form, it checks from the session to see if the token given by the form is exactly the same session found in the session. If it's true, then process the request else it's a double submission.
Example:
public class AuthenticationAction extends Action {
public void displayLogout(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
saveToken(request);
return mapping.findForward("displayLogout");
}
public ActionForward doLogout(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
if (isValidToken(request)) {
//It wasn't yet a double submission, delete token generated by Struts
resetToken(request);
//logout.
...
//return back home
return mapping.findForward("home");
} else {
//Double submission..
throw new Exception("double submission");
}
}
}
A better tutorial is found here.
Hmm, you can also use the Spring Webflow framework if you want, but the use of the back and refresh not submitting your forms twice can easely be solved by defining your controller right. I think the use of REST can also help solve some problems.
The hiddenfield manipulation is another thing since a hiddenfield can always be viewed in the source of your page. And if the field can be viewed then it is open to manipulation.
To avoid re-inventing the wheel, using an existing framework seems to be the best solution. Struts looks like a good candidate. A simple introduction tutorial is available.

Several different login forms for Spring Security

I'm using spring-security web authentication with spring-mvc with a custom authentication and all is well so far:
My problem is: /login loads a view with a fully-featured page, but now I have to provide authentication for iframe/popup format (e.g. for an authenticated bookmarklet), so loading a different view (or with different parameters).
I see two solutions that are not overcomplicated:
In my /login action, I have a way (unkown to me so far) to retrieve the original request and check it against a set of URLs that use the simpler view, then choose the matching view. => How do I retrieve this original request?
I make another login action/form, say /login/minimal, which also POSTs to the spring security URL /j_spring_security_check, but I need to implement the request storage/retrieval mechanism, so that the original request is performed after successful login. => I see this has something to do with SecurityContextPersistenceFilter, yet I don't know how to implement it or call it.
If I understand your question correctly, you're looking to vary the login page based on the original request string. Check out this forum post for accessing the original request url from the session. It's for an older version, but you should be able to use it to get started.
Edit I haven't had a chance to validate this, but it looks like the key changed between Acegi security and Spring Security 3. It looks like you can access it from session using the constants in the WebAttributes class. Effectively
//request is a HttpServletRequest object
SavedRequest savedRequest = (SavedRequest)request.getSession().getAttribute(WebAttributes.SAVED_REQUEST);
String url = savedRequest.getRequestURL();
For your first question:
there is a class org.springframework.security.web.authentication.WebAuthenticationDetails
It contains only the IP of the client and its Session, but
it has a method
protected void doPopulateAdditionalInformation(HttpServletRequest request) {}
I belive you could enhance this by subclassing and add the request url. -- But check first if the request is the request from the login form, or the "blocked" request.
Added
Chris Thompson posted an other part of the puzzle to answer your question:
He mentioned that the saved request can be obtained from the session:
//request is a HttpServletRequest object
SavedRequest savedRequest = (SavedRequest)request.getSession().getAttribute(WebAttributes.SAVED_REQUEST);
String url = savedRequest.getRequestURL();
So you can combine this, instead of enhanding the WebAuthenticationDetails you just need to read its already inclueded session.
#see Chris Thompson answer

Java Web App: Passing form parameters across multiple pages

what is the best practice or best way of passing form parameters from page to page in a flow? If I have a flow where a user enters data in a form and hits next and repeats this process until they get to an approval page, what ways could I approach this problem to make the retention of data as simple as possible over the flow?
I guess you could put all the information as you go in the session but could you get into memory issues if a lot of people are using your app and going through the flow at the same time?
You can store data into Cookies or store them into Session and access them between different web pages.
HttpSession is your best bet if you want to track a "wizard" style data entry.
Just seconding #Rachel's openion.
The server side component that handles your page submits ( such as Servlets) would have some code like:
public void doPost (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
HttpSession session = req.getSession();
session.setAttribute("Variable1", request.getParameter("input1"));
//and so on..
HttpSession Provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user.
You may also put attributes in the request scope. They are accessed the same way from EL in your JSPs, but do not require a session. Depending on your situation, you may not wish to start sessions for every user.

Categories

Resources