Maintaining State Using Sessions Part 1
1. Why sessions are necessary
#####[Slide 1]
- HTTP is a stateless protocol, and HTTP sessions provide a way to track users, such as an Amazon shopping cart.
- HTTP sessions are used to maintain state, such as the items in a shopping cart.
- HTTP sessions are a way to remember users, for example, their Amazon user name.
- HTTP sessions are used to manage workflow, as demonstrated in our example of registering a charity in an online database.
2. Working with cookies and URL parameters
#####[Slide 2]
- A session is a data object maintained by the server or web application, containing user-related information.
- To enable the browser to “track” the session, the server generates a SessionID string that is sent back to the browser on every request.
```java
class HttpSession {
+invalidate(): void
+getAttribute(name: String): Object
+getAttributeNames(): Enumeration<String>
+getCreationTime(): long
+getId(): String
+getLastAccessedTime(): long
+getMaxInactiveInterval(): int
+removeAttribute(name: String): void
+setAttribute(name: String, value: Object): void
+setMaxInactiveInterval(interval: int): void
}
note "Enumeration is a Java interface representing a sequence of elements." as Enumeration
HttpSession "1" --> "*" Enumeration : returns
- HTTP sessions are a way to remember users, such as their Reddit user name.
- HTTP sessions are used to manage workflow, as demonstrated in our example of registering a charity in an online database.
#####[Slide 3]
- HTTP 1.1 defines session cookies HTTP Cookie, which can be sent from the web server to the browser and stored locally by the browser to be sent back. This is how the JSESSIONID will be “persisted” on the client browser side during a session.
- SessionID is passed in the URL query string from the server to the client-side web browser after a session has been established on the web server. This process is called URL rewriting and can be used when cookies have been disabled on the client user browser. The JEE8 platform includes the API tools to handle sessions.
- Security is a major concern when using sessions. OWASP Security Testing Guide provides useful information on session management testing, including session hijacking attacks.
- The best way to secure your session in Tomcat 9 is with SSL. SSL/TLS Configuration How-To offers guidance on configuring SSL.
3. How to store data in a session
This is where we start adding session data in our charity-registration web application example.
1. Ensure we have the <jsp-config>
tag, the base.jspf
file, and the redirect in our index.jsp
landing page.
2. We configure our session in the web.xml
as in the following example: Oracle Weblogic documentation
<session-config>
<!-- Time before an inactive session is invalidated -->
<session-timeout>30</session-timeout>
<!-- When using tracking-mode of COOKIE -->
<cookie-config>
<!-- Custom name of the Session -->
<name>JSESSIONID</name>
<domain>nicordesigns.com</domain>
<path>/registrations</path>
<!-- Adds a comment to a cookie -->
<comment>This is a comment</comment>
<http-only>true</http-only>
<secure>false</secure>
<!-- Time a cookie will be persisted on the client browser -->
<max-age>1800</max-age>
</cookie-config>
<!-- Specifies how the server will implement the Session URL, COOKIE, SSL, and order -->
<tracking-mode>COOKIE</tracking-mode>
</session-config>
Here, the tags are optional, but the order is required. Additionally, some configurations can be done programmatically using the ServletContext.
An example of setting session-timeout
programmatically:
HttpSession session = request.getSession();
session.setMaxInactiveInterval(10 * 60);
We will be using the charity-registration
module with the Session Servlet to demonstrate this.
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
3. Storing and Retrieving Data
CharitySessionServlet
@WebServlet(
name = "charitySessionServlet",
urlPatterns = "/charitySession"
)
public class CharitySessionServlet extends HttpServlet {
private final Map<Integer, String> categories = new Hashtable<>();
public CharitySessionServlet() {
this.categories.put(1, "Animals");
this.categories.put(2, "Arts, Culture, Humanities");
this.categories.put(3, "Community Development");
this.categories.put(4, "Education");
this.categories.put(5, "Environment");
this.categories.put(6, "Health");
}
// Rest of the class implementation...
}
4. Using Sessions in the Charity Session Servlet
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getParameter("action");
if (action == null)
action = "browse
";
switch (action) {
case "addToCharitySession":
this.addToCharitySession(request, response);
break;
case "emptyCharitySessionObject":
this.emptyCharitySessionObject(request, response);
break;
case "viewCharitySession":
this.viewCharitySession(request, response);
break;
case "browse":
default:
this.browse(request, response);
break;
}
}
5. Using Sessions in JSP
browse.jsp
<%@ page import="java.util.Map" %>
<!DOCTYPE html>
<html>
<head>
<title>Charity Category List</title>
</head>
<body>
<h2>Charity Category List</h2>
<a href="<c:url value="/charitySession?action=viewCharitySession" />">
View Charity Session Data Object</a><br /><br />
<%
@SuppressWarnings("unchecked")
Map<Integer, String> categories =
(Map<Integer, String>) request.getAttribute("categories");
for (int id : categories.keySet()) {
%><a href="<c:url value="/charitySession">
<c:param name="action" value="addToCharitySession" />
<c:param name="categoryId" value="<%= Integer.toString(id) %>"/>
</c:url>"><%= categories.get(id) %></a><br /><%
}
%>
</body>
</html>
viewCharitySessionObject.jsp
<%@ page import="java.util.Map" %>
<!DOCTYPE html>
<html>
<head>
<title>View Charity Session Object</title>
</head>
<body>
<h2>View Charity Session Object</h2>
<a href="<c:url value="/charitySession" />">Charity Category List</a><br /><br />
<a href="<c:url value="/charitySession?action=emptyCharitySessionObject" />">
Empty Charity Session Object</a><br /><br />
<%
@SuppressWarnings("unchecked")
Map<Integer, String> categories =
(Map<Integer, String>) request.getAttribute("categories");
@SuppressWarnings("unchecked")
Map<Integer, Integer> categoryHolder =
(Map<Integer, Integer>) session.getAttribute("categoryHolder");
if (categoryHolder == null || categoryHolder.size() == 0)
out.println("Your category holder is empty.");
else {
for (int id : categoryHolder.keySet()) {
out.println(categories.get(id) + " (qty: " + categoryHolder.get(id) +
")<br />");
}
}
%>
</body>
</html>
HttpSession.getId()
retrieves the Session Id.getCreationTime()
: Gets the time when the session was created.getLastAccessedTime()
: Gets the last time the user accessed the session.isNew()
: Returnstrue
if the session was created during the current request.getMaxInactiveInterval()
: Gets the maximum time that the session can be inactive.setMaxInactiveInterval()
: Sets the time that the session can be inactive (<session-timeout>
).invalidate()
: Removes the current session and its data.
5. Compiling, testing, and debugging our charity-session web application
We will examine all the functionality provided by our app and also explore what happens with the session when you close the browser.