Cookies and Sessions

1 Cookie

1.1 Introduction

Cookie (HTTP Cookie) is a small text information that is sent by the server to the user’s browser and then stored on the user’s computer. Cookies are usually used to track user session information, personalized settings, shopping cart contents, etc., to maintain state information between different HTTP requests.
After the client has a cookie, each request is sent to the server. Each cookie cannot exceed 4kb in size.

1.2 Browser View Cookie

For example, to view Cookies on Google Chrome, press F12 to view Cookies in Application in DevTools:

The attributes of Cookie are shown in the following table:

Why does Cookie need to set the HttpOnly and Secure attributes?
When the HttpOnly attribute is set, cookie information cannot be obtained through scripts, which is mainly used to prevent XSS attacks. Once the Secure attribute is set, the browser can only access the cookie under the HTTPS protocol communication between the front and back ends. When using the HTTP protocol, the browser cannot obtain the cookie information, which also protects the cookie information.

1.3 Create Cookie


Sample code:

@WebServlet("/create-cookie")
public class CookieServlet extends HttpServlet {<!-- -->

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<!-- -->
        response.setContentType("text/html; charset=UTF-8");
        Cookie c1 = new Cookie("key1", "kong");
        Cookie c2 = new Cookie("key2", "xing");

        response.addCookie(c1);
        response.addCookie(c2);
        response.getWriter().print("Cookie added successfully");
    }
}

View Cookies in the Application in the browser DevTools:

1.4 Server obtains Cookie


How normal people write:

CookieUtils tool class:

public class CookieUtils {<!-- -->

    public static Cookie findCookie(String name, Cookie[] cookies){<!-- -->
        if (name == null || cookies == null || cookies.length == 0) {<!-- -->
            return null;
        }
        for (Cookie cookie : cookies) {<!-- -->
            if (name.equals(cookie.getName())) {<!-- -->
                return cookie;}
        }
        return null;
    }
}

Servlet:

@WebServlet("/CookieServlet1")
public class CookieServlet1 extends HttpServlet {<!-- -->

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<!-- -->
        getCookie(request,response);
    }

    protected void getCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<!-- -->
        response.setContentType("text/html; charset=UTF-8");
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {<!-- -->
            // The getName method returns the key (name) of the Cookie
            // The getValue method returns the value of Cookie
            response.getWriter().write(cookie.getName() + "=" + cookie.getValue() + "<br/>");
        }
        Cookie iWantCookie = CookieUtils.findCookie("key1", cookies);

        if (iWantCookie != null) {<!-- -->
            response.getWriter().write("The required Cookie was found");
        }
    }
}

How to write new JDK features:

@WebServlet("/getCookie")
public class CookieCreate extends HttpServlet {<!-- -->

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<!-- -->
        Optional<Cookie> c1 = getCookie("key1",request.getCookies());
        Optional<Cookie> c2 = getCookie("key2",request.getCookies());

        System.out.println(c1.get().getName() + " | " + c1.get().getValue());
        System.out.println(c2.get().getName() + " | " + c2.get().getValue());

        Cookie c3 = getCookie("key3", request.getCookies()).orElse(new Cookie("key3", "empty"));
        System.out.println(c3.getName() + " | " + c3.getValue());
    }

    private Optional<Cookie> getCookie(String name,Cookie[] cookies){<!-- -->
       return Arrays.stream(cookies).filter(c->name.equals(c.getName())).findFirst();
    }
}

1.5 Modification of Cookie Value

Option One:

// 1. First create a Cookie object with the same name to be modified.
// 2. In the constructor, assign a new Cookie value at the same time.
Cookie cookie = new Cookie("key1","newValue1");
// 3. Call response.addCookie(Cookie); notify the client to save changes
resp.addCookie(cookie);

Option II:

//Option 2:
// 1. First find the Cookie object that needs to be modified.
Cookie cookie = CookieUtils.findCookie("key2", req.getCookies());
if (cookie != null) {<!-- -->
// 2. Call the setValue() method to assign a new Cookie value.
cookie.setValue("newValue2");
// 3. Call response.addCookie() to notify the client to save changes
resp.addCookie(cookie);
}

The expires attribute in 1.6 Cookie

Cookie life control refers to how to manage cookies and when they are destroyed (delete)
setMaxAge()

  • Positive number, indicating expiration after the specified number of seconds
  • A negative number means that the cookie will be deleted as soon as the browser is closed (the default value is -1)
  • Zero means the cookie will be deleted immediately
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {<!-- -->
response.setContentType("text/html; charset=UTF-8");
Cookie c1 = new Cookie("key1", "value1");
Cookie c2 = new Cookie("key2", "value2");
Cookie c3 = new Cookie("key3", "value3");
c3.setMaxAge(60 * 60 * 24); //One day
Cookie c4 = new Cookie("key4", "value4");
c4.setMaxAge(-1);
Cookie c5 = new Cookie("key5", "value5");
c5.setMaxAge(0);
\t
response.addCookie(c1);
response.addCookie(c2);
response.addCookie(c3);
response.addCookie(c4);
response.addCookie(c5);
response.getWriter().print("Cookie added successfully");
}

View Cookies in the Application in the browser DevTools:

Domain and Path attributes in 1.7 Cookie

The default value of Cookie’s Domain is request.getServletName
The default value of Cookie’s Path is request.getContextPath

http://localhost:8080/cookie-demo/create-cookie //Generate cookies
http://127.0.0.1:8080/cookie-demo/create-cookie //The cookie generated above cannot be accessed

Learned that cookies cannot be accessed across domains

experiment one:
The Path matching rule for Cookie is, prefix matching

path = /;
path = /cookie-demo;
path = /cookie-demo/a.jsp;
The above cookie accesses /cookie-demo/a.jsp and will be accessed along with the request;
The cookie accessing /cookie-demo/a.jsp with path = /cookie/b.jsp will not be accessed along with the request;

Experiment 2: Sharing cookies in different subdomains
Local domain name resolution
In this path C:\Windows\System32\drivers\etc\hosts add the following content:

127.0.0.1 file.com
127.0.0.1a.file.com
127.0.0.1 b.file.com
127.0.0.1 image.com

Code:

 @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<!-- -->
Cookie c10 = new Cookie("key10", "value10");
c10.setDomain("file.com");
Cookie c11 = new Cookie("key11", "value11");
c11.setDomain("a.file.com");
Cookie c12 = new Cookie("key12", "value12");
c12.setDomain("b.file.com");
Cookie c13 = new Cookie("key13", "value13");
c13.setDomain("image.com");

response.addCookie(c10);
        response.addCookie(c11);
        response.addCookie(c12);
        response.addCookie(c13);
}

Visit http://a.file.com:8080/cookie-demo/create-cookie to generate a cookie
Visit http://b.file.com:8080/cookie-demo/get-cookie. Only the c10 cookie set with the top-level domain can be shared and accessed by subdomains.

Summary: Only the current domain and the top-level domain of the current domain can be set in the cookie (for example, when accessed by a.file.com, the cookie can be set to
a.file.com, file.com)

The path attribute of Cookie can effectively filter which Cookies can be sent to the server. Which ones are not posted.
The path attribute is used to effectively filter by the requested address.

Access Cookies in 1.8 JS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/js.cookie.min.js"></script>
</head>
<body>
  <script>
      console.log(Cookies.get("key10"));

      Cookies.set('key21', 'value21', {<!-- --> expires: 7, path: '/cookie-demo' })

      Cookies.set('key22', 'value22', {<!-- --> expires: 7, path: '/cookie-demo', domain: ".file.com" })

      Cookies.set('key23', 'value23', {<!-- --> expires: 7, path: '/cookie-demo', domain: ".image.com" })
      
      console.log("-------------------")
      console.log(Cookies.get());
  </script>
</body>
</html>

First use http://a.file.com:8080/cookie-demo/create-cookie to generate cookies
Then use http://a.file.com:8080/cookie-demo/c.html to get cookies

View the console print in the Console in the browser DevTools:

View Cookies in the Application in the browser DevTools:

2 Session

2.1 Introduction

Session usually refers to a user session in a web application. It is a state information maintained on the server side and used to track the interaction between the user and the application. Sessions allow the user’s state to be maintained while the user navigates the website, allowing the user’s data to be stored and retrieved, such as login status, shopping cart contents, user preferences, etc.

Here are some important concepts and usage of sessions:

  1. Creation of session: A session is usually created when a user accesses a web application. When a user visits a website for the first time, the server creates a unique session identifier (Session ID) for him or her and stores it in a cookie or passes it to the client through URL rewriting, etc.

  2. Data storage and retrieval: Within a session, developers can store various types of data, including the user’s login information, shopping cart contents, user preferences, and more. This data is stored server-side, associated with the user’s session, and persists across sessions.

  3. Session life cycle: Sessions can have different life cycles, usually divided into the following types:

    • Session-level: A session begins when the user first accesses the web application and continues until the user closes the browser or the session times out.
    • Request-level: The session is only valid during a single HTTP request and will not be persisted.
    • Application-level: Data is stored throughout the life cycle of the web application and shared with all users.
  4. Session timeout: In order to avoid wasting resources, sessions usually have a timeout period, that is, sessions that are inactive within a certain period of time will be destroyed. The timeout can be set in the application configuration.

  5. Session management: Session management includes operations to create, destroy, store, and retrieve session data. Developers can use APIs provided by web frameworks or servlet containers for session management. Commonly used APIs include the HttpSession interface and related methods.

  6. Session security: Session security is critical to user privacy and data protection. Developers need to take steps to prevent attacks such as session hijacking and session fixation, such as using secure session identifiers and the HTTPS protocol.

2.2 Login Case

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form action="/session-demo/login" method="post">
        Username: <input type="text" name="username"><br>
        Password: <input type="password" name="password"><br>
        <input type="submit">
    </form>
</body>
</html>

LoginServlet

@WebServlet("/login")
public class LoginServlet extends HttpServlet {<!-- -->

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<!-- -->
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        HttpSession session = request.getSession();

        if("kong".equals(username) & amp; & amp; "123456".equals(password)){<!-- -->
            session.setAttribute("loginUser","kong");
            response.sendRedirect("/session-demo/getUser");
        }else {<!-- -->
            response.sendRedirect("/session-demo/login.html");
        }
    }
}

View currently logged in users
GetUserServlet

@WebServlet("/getUser")
public class GetUserServlet extends HttpServlet {<!-- -->

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<!-- -->
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        HttpSession session = request.getSession();
        String loginUser = session.getAttribute("loginUser").toString();
        out.println("User: " + loginUser);
    }
}

2.3 Cookie-session principle

First request:

View Cookies in the Application in the browser DevTools:

Second request to the server:

2.4 Session API operations

Session API is a set of interfaces and classes used to manage sessions in Java web applications. Sessions allow you to store and share data between different HTTP requests to maintain stateful information between users and applications.

The following are some commonly used Session operations and their sample codes:

  1. Get Session object:

    HttpSession session = request.getSession();
    
  • true: Default, if the current context has a session, use the current session, if no new session is generated

  • false: Get the session in the current context. If the current context does not have a session, it will not actively generate a session.

    This will get the Session object for the current HTTP request and create a new Session if it does not exist.

  1. Store data in Session:

    session.setAttribute("username", "john_doe");
    

    This will store an attribute called “username” in the Session with the value “john_doe”.

  2. Get data from Session:

    String username = (String) session.getAttribute("username");
    

    This will get the value of the attribute named “username” from the Session.

  3. Delete data in Session:

    session.removeAttribute("username");
    

    This will remove the attribute named “username” from the Session.

  4. Set Session timeout:

    session.setMaxInactiveInterval(3600); //Set the Session timeout to 1 hour, in seconds
    

    This will set the maximum inactivity interval of the Session to 1 hour, and the Session will be destroyed when the user has no activity for an hour.

  5. Destroy Session:

    session.invalidate();
    

    This will immediately destroy the Session and clear all data in it.

  6. Get Session ID:

    String sessionId = session.getId();
    

    This will get the session’s unique identifier (ID).

The default session timeout is 30 minutes. Because the configuration file web.xml of the Tomcat server has the following configuration by default, it means that all Session timeout configurations under the current Tomcat server are configured. The default length is: 30 minutes.

<session-config>
<session-timeout>30</session-timeout>
</session-config>