Session technology

(1) Overview, purpose and classification

(1) Basic overview

Overview: A session is multiple requests and responses between the browser and the server

In other words, the multiple requests and responses generated by the content from the time the browser accesses the server to the time the browser closes down are collectively called a session between the browser and the server

(2) Why use conversational technology?

In fact, the session problem solves the communication problem between the client and the server. Through some session technologies, the data of each user can be stored in the form of cookie/session, which is convenient for users to access web resources in the future

Scenario: AFTER A and B log in to an online shopping mall, A buys an HHKB keyboard and B buys A folk guitar. All the information will be saved

The purpose is to save account information, ask whether to automatically log in in the future when logging in, or analyze what kind of goods users like according to the browse and purchase before, and make accurate push

Can we use the HttpServletRequest and ServletContext objects that we’ve studied before to hold this data? The answer is no

HttpServletRequest cannot be used because: We have multiple requests and responses in a single session, and each request from the browser client generates an HttpServletRequest object that only holds information about the request. For example, putting in a shopping cart is a different request than paying for a purchase. Obviously, the data is not being handled well

Why you can’t use ServletContext: The ServletContext object is shared by the entire Web application, and storing data there makes it impossible to identify where the information belongs

(3) classification

Client session technology – Cookie

Server Session technology — Session

Cookie technology

(1) Basic understanding

(1) overview

Cookies can be simple to understand for the server temporary exist some information file in your web browser, it will be you the entered some content on the website, or record some options, the next time you visit the same site, the server will be active to query the cookie information, if any, will be according to the content, Provide some special functions, such as remembering account numbers and passwords

To sum it up:

  • Web pages interact with each other through THE HTTP protocol, which is a stateless protocol (after the data is submitted, the link between the browser and the server is closed and a new connection needs to be established during the interaction).
  • The server cannot confirm the user’s information, so it issues each user a pass through which to confirm the user’s information

(2) Specific process

When the browser accesses the server, if the server needs to record the status of the user, it sends a cookie to the browser with response, and the browser will save the cookie. When the browser visits the server again, the browser submits the requested URL to the server along with the Cookie

(3) specification

  • Cookie size limit: 4KB

  • A server can store up to 20 cookies on the client browser;

  • A maximum of 300 cookies can be saved in a browser

    The above data is the HTTP Cookie specification, but now some browsers may make some extensions to the Cookie specification, such as the size of each Cookie is 8KB, can save up to 500 cookies and so on

Cookies are not shared between browsers

(2) Common apis

// Add a corresponding set-cookie header field to its response header
addCookie

// Used to get the Cookie submitted by the client
GetCookie
public Cookie(String name,String value)
   
// This method sets the value associated with the cookie.
setValue

// This method gets the value associated with the cookie.
getValue

// This method sets the time (in seconds) for the cookie to expire. If not, the cookie will remain valid only for the duration of the current session.
setMaxAge

// This method returns the maximum lifetime (in seconds) of the cookie. By default, -1 means that the cookie will persist until the browser closes
getMaxAge

// This method sets the path to which the cookie applies. If you do not specify a path, all urls in the same directory as the current page (including subdirectories) will return cookies.
setPath

// This method gets the path to which the cookie applies.
getPath

// This method sets the domain to which the cookie applies
setDomain

// This method gets the domain to which the cookie applies
getDomain
Copy the code

Note: (1)

  • Cookies are not cross-domain names
  • Ookie to save Chinese garbled characters: Chinese characters belong to Unicode characters, English data Ascii characters, Chinese 4 characters or 3 characters, English 2 characters, Cookie use Unicode characters need to encode Unicode characters
Cookie cookie = new Cookie("xxx",URLEncoder.encode(name,"UTF-8"));
Copy the code

(2) the period of validity

The setMaxAge() method allows you to set the validity period of the Cookie

  • If MaxAge is positive, the browser writes the Cookie to the hard drive, and the Cookie is valid when you log in to the web site as long as it is seconds before MaxAge. If MaxAge is negative, the Cookie is temporary and valid within the browser. If you close the browser, the cookies are invalid and are not written to the hard drive. The default value of Cookie is -1
  • If MaxAge is 0, the Cookie is deleted

(3) Delete and modify

Cookies are stored like Map sets, with names and values, except that both are strings

Modify the

String name = "On a windy day."; Cookie cookie =new Cookie("country",URLEncoder.encode(name,"UTF-8"));
Copy the code

delete

String name = "On a windy day."; Cookie cookie =new Cookie("country",URLEncoder.encode(name,"UTF-8"));

cookie.setMaxAge(0);
response.addCookie(cookie);

printWriter.writer("Cookie has been deleted.")
Copy the code

(3) The domain name of Cookie

The domain attribute of a Cookie determines the domain name at which the Cookie is accessed. The value of Deomain is specified as “. The domain name”

Cookie privacy security mechanism determines that cookies are not cross-domain. Even if the level-1 domain name is the same, different level-2 domain names cannot be transferred, eg: www.ideal.com and www.image.. com

If I want cookies between web pages with the same level 1 domain to be accessible to each other, I need to use the domain method

Cookie cookie = new Cookie("name","admin"); cookie.setMaxAge(1000); cookie.setDomain(".ideal.com); response.addCookie(cookie); Printwriter. writer(" use www.ideal.com domain name to add a Cookie, as long as the level 1 domain name is ideal.com ")Copy the code

(4) Path of Cookie

The path attribute of a Cookie determines the path that is allowed to access the Cookie

Generally speaking, when cookies are published, the resources of the entire web page can be used. However, if only a certain Servlet can obtain cookies, other resources cannot or do not need to be obtained

Cookie cookie = new Cookie("name","admin"); cookie.setPath("/Servlet); cookie.setMaxAge(1000); response.addCookie(cookie); Printwriter. writer(" This Cookie is only accessible in Servlet1 ")Copy the code

(5) Cookie security attributes

The HTTP protocol is not only stateless, it’s also insecure! If you do not want the Cookie to be transmitted over insecure protocols, you can set the secure attribute of the Cookie to true so that the browser will transmit the Cookie only over secure protocols such as HTTPS and SSL

Setting the secure attribute does not encrypt the Cookie contents. To ensure security, use md5 encryption

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Set the data format and encoding of the response body
        resp.setContentType("text/html; charset=utf-8");

        // Get all cookies
        Cookie[] cookies = req.getCookies();
    	//// No cookie for lastTime
        boolean flag = false;
        // Iterate through the cookie array
        if(cookies ! =null && cookies.length > 0) {for (Cookie cookie : cookies) {
                // Get the name of the cookie
                String name = cookie.getName();
                // Determine if the name is: lastTime
                if("lastTime".equals(name)){
                    // Not the first visit

                    flag = true;// Time with access records

                    // Set the value of the Cookie
                    // Get the current time string, reset the Cookie value, and resend the Cookie
                    Date date  = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("Yyyy MM Month DD day HH: MM :ss");
                    String str_date = sdf.format(date);
                    System.out.println("Before coding:"+str_date);
                    / / URL encoding
                    str_date = URLEncoder.encode(str_date,"utf-8");
                    System.out.println("After coding:"+str_date);
                    cookie.setValue(str_date);
                    // Set the lifetime of the cookie
                    cookie.setMaxAge(60 * 60 * 24 * 30);/ / for a month
                    resp.addCookie(cookie);

                    // Response data
                    // Obtain the value of the Cookie
                    String value = cookie.getValue();
                    System.out.println("Before decoding:"+value);
                    / / URL decoding:
                    value = URLDecoder.decode(value,"utf-8");
                    System.out.println("After decoding:"+value);
                    resp.getWriter().write("

Welcome back, your last visit was :"

+value+"</h1>"); break; }}}if(cookies == null || cookies.length == 0 || flag == false) {// No, first visit // Set the value of the Cookie // Get the current time string, reset the Cookie value, and resend the Cookie Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("Yyyy MM Month DD day HH: MM :ss"); String str_date = sdf.format(date); System.out.println("Before coding:"+str_date); / / URL encoding str_date = URLEncoder.encode(str_date,"utf-8"); System.out.println("After coding:"+str_date); Cookie cookie = new Cookie("lastTime",str_date); // Set the lifetime of the cookie cookie.setMaxAge(60 * 60 * 24 * 30);/ / for a month resp.addCookie(cookie); resp.getWriter().write("

Hello, welcome to your first visit

"
); }}Copy the code

Character[32] : Character[32] : Character[32] : Character[32] : Character[32]

Alternatively, you can run a Demo that shows you the last item you saw

Session

(I) Overview

Sessions are another mechanism for recording the state of the browser. Cookies are stored in the browser and sessions are stored in the server. When a user accesses the server using a browser, the server records the user’s information in some form on the server, and that’s called a Session

Why do you use a Session because a Session can store objects, and a Cookie can only store strings which solves a lot of problems that cookies can’t solve

(二) API

// Obtain the time when the Session was created
long getCreationTime(a)

// Obtain the Session ID
String getId(a)

// Return the last active time of the Session
long getLastAccessedTime(a)

// Get the ServletContext object
ServletContext getServletContext(a)

// Set the Session timeout period
void setMaxInactiveInterval(int var1)

// Obtain the timeout duration of the Session
int getMaxInactiveInterval(a)

// Get the Session attribute
Object getAttribute(String var1)

// Get all attribute names of the Session
Enumeration getAttributeNames(a)

// Set Session properties
void setAttribute(String var1, Object var2)

// Remove the Session attribute
void removeAttribute(String var1)

// Destroy the Session
void invalidate(a)

// Whether the Session is new
boolean isNew(a)
Copy the code

Session has a method similar to request and ServletContext. Session is also a domain object. Session is a mechanism for recording the state of the browser. As long as the Session object is not destroyed, servlets can communicate with each other through the Session object

Set up the

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession httpSession = request.getSession();
		httpSession.setAttribute("name"."test");
	}
Copy the code

To obtain

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession httpSession = request.getSession();
		String value = (String) httpSession.getAttribute("name");
		System.out.println(value);
	}
Copy the code

(3) Life cycle and validity period

The first time a user accesses a server Servlet, JSP, or other dynamic resource, the Session object is automatically created. The Session object is stored in memory. This is why the above example can directly use the request object to obtain the Session object

If you access HTML, static resources like images are not created

After a Session is generated, as long as the user continues to access the Session, the server will update the last access time of the Session, regardless of whether to read or write the Session, the server will consider the Session active once.

As more and more users access the server, there will be more and more sessions. In order to prevent memory overflow, the server will delete a Session from memory that has not been active for a long time, which is the timeout of the Session

The default timeout duration of a Session is 30 minutes. You can change the timeout duration in three ways

The first method is to set the time value to 20 minutes in the tomcat/conf/web. XML file, which is valid for all Web applications ————

20

The second method is set in a single web. XML file. This method is valid for a single Web application

The third method is to use the setMaxInactiveInterval() method

httpSession.setMaxInactiveInterval(60);
Copy the code

(4) Small differences between Session and Cookie

  • The Session period is the amount of time that you are inactive, so if we set the Session to 10s, within 10s, there is no access to the Session, the property in the Session is invalid, and if at 9s, you access the Session, it will be timed again

  • The invalidate() method invalidates all properties of a Session and is often used to exit safely

  • If you want to invalidate a Session attribute, use the removeAttribute method

  • The lifetime of a Cookie is calculated as the cumulative time, regardless of whether the user has accessed the Session or not

(5) of the Session

Problem: I set the Session attribute in Aservlet and get the attribute of A in Bservlet

In the browser, create a new page to access the Bservlet again, the null pointer exception is reported

Now the question is: how does the server implement a session to serve a user’s browser? Put another way: Why can a server provide different sessions for different user browsers?

The HTTP protocol is stateless, and a Session cannot determine whether it is the same user based on the HTTP connection. The server sends a Cookie named JESSIONID to the user’s browser, whose value is the Session ID value. The Session actually uses cookies to identify the same user.

To put it simply: Sessions are able to identify different users by relying on cookies

The Cookie is automatically issued to the browser by the server and does not need to be created manually. The default maxAge value of the Cookie is -1, which means that the Cookie is only used by the current browser and is not stored in the hard disk

Process overview:

  • When you access the Aservlet, the server creates a Session object, executes our program code, executes our program code, and automatically issues a Cookie to the user’s browser
  • When I use the same browser to access the BServlet, the browser will pass the Cookie value over Http to the server, and the server will know which Session to use
  • When we use the new Session’s browser to access the BServlet, the new browser does not have a Cookie, and the server cannot recognize which Session is being used, so it does not get the value.

(vi) Use of Session after Cookie is disabled by browser

Two situations are encountered: 1. Cookie is disabled in the user’s browser. Most mobile browsers do not support cookies

Java Web provides a solution: URL rewriting

The HttpServletResponse class provides two METHODS for URL rewriting:

encodeURL(String url)

encodeRedirectURL(String url)
Copy the code

It is worth noting that: These methods automatically determine if the browser supports cookies. If the browser supports cookies, the URL will be rewritten without a JSessionID. The first time the URL is printed, the jSessionID will still appear (because there are no cookies).

example

String url = "/web-01/Servlet5";
response.sendRedirect(response.encodeURL(url));
Copy the code

How URL rewriting works:

The Session id is rewritten to the URL summary. The server parses the rewritten URL to obtain the Session ID. In this way, even if the browser disables the Cookie, the Session ID is passed through the server, and the Session status can still be recorded using the Session.

(7) Session cases

Example 1: Using the Session to complete simple login

Create the User class first

public class User {
	private String username = null;
	private String password = null;
	
	public User(a) {}public User(String username, String password) {
		super(a);this.username = username;
		this.password = password; }... Various set get methodsCopy the code

Simulate a database using a simple collection

public class UserDB {
	private static List<User> list =new ArrayList<>();
	
	static {
		list.add(new User("admin"."888"));
		list.add(new User("aaa"."111"));
		list.add(new User("bbb"."222"));
	}
	
	// Find the user by user name and password
	public static User find(String username, String password) {
		
		for (User user:list) {
			if (user.getUsername().equals(username)&& user.getPassword().equals(password)) {
				returnuser; }}return null; }}Copy the code

Form submission we write in JSP (imitation can post say JSP)

public class UserDB {
	private static List<User> list =new ArrayList<>();
	
	static {
		list.add(new User("admin"."888"));
		list.add(new User("aaa"."111"));
		list.add(new User("bbb"."222"));
	}
	
	// Find the user by user name and password
	public static User find(String username, String password) {
		
		for (User user:list) {
			if (user.getUsername().equals(username)&& user.getPassword().equals(password)) {
				returnuser; }}return null; }}Copy the code

Get the data from the form submission and find out if the database has a corresponding user name and password

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		
		User user = UserDB.find(username, password);
		
		// If not, there is an error in the user name or password
		if (user == null) {
			response.getWriter().write("User name or password error, login failed!");
			return;
		}
		
		// Indicates that the user has logged in
		HttpSession httpSession = request.getSession();
		httpSession.setAttribute("user", user);
		
		// Go to another page and tell the user that the login is successful
		response.sendRedirect(response.encodeURL("test.jsp"));
	}
Copy the code

Case 2: Use Session to prevent duplicate form submission

Hazards of duplicate submission:

In the vote on the web page to submit, to achieve the effect of brushing votes.

Register multiple users, constantly post, disturb the normal Posting order.

There are two common types of duplicate submissions

First: back up and submit

Second: network latency, multiple click submit button

sketch

Solution:

Network latency problem:

The second type of network delay, which causes multiple submissions to the server, is actually a client-side problem and can be prevented by using javaScript

→ When the user clicks the submit button for the first time, the data is submitted to the server. When the user clicks the submit button again, the data is not submitted to the server

Listen for events. You can only allow the user to submit the form once:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> < HTML > <title Type ="text/javascript"> var isCommitted = false; If (isCommited == false){isCommited = true; if (isCommited == false); return true; }else{ return false; }} </script> </head> <body> <form action="/web-01/Lservlet" method="post" onsubmit="return doSubmit()"> </form> </body> </ HTML >< /form>Copy the code

Refresh back to submit problem:

We know that a Session can be used to indicate whether or not a user is logged in. The principle of sessions is also stated: different user browsers have different sessions. Why not request and ServletContext? The domain object of the request can only be used for one HTTP request. The data of the domain object of the request cannot be retrieved when the form data is submitted. The ServletContext represents the entire Web application. If several user browsers access the ServletContext domain object at the same time, the data in the ServletContext domain object will be overwritten multiple times, which means the data in the Domain object will be meaningless.

At this point, it occurs to us that there is also a hidden field in the form that can be used to deliver data to the server.

A: Determine whether the data of the Session domain object corresponds to the data submitted by the JSP hidden domain.

B: Determine whether the data in the hidden field is empty.

C: If the Session domain object is empty, the Session domain object is empty. If the Session domain object data is empty, the Session domain object data is empty.

D: What exactly is the data we store into the Session domain object? A simple number? Well, that sounds like it. As long as the data in the Session domain is matched to the data in the JSP hidden domain, the Session data will be removed immediately after the Servlet decides whether to repeat the commit. More technically, the data stored in the Session field object is a random number.

public class TokenProcessor {
	private TokenProcessor(a) {}private final static TokenProcessor TOKEN_PROCESSOR = new TokenProcessor();

	public static TokenProcessor getInstance(a) {
		return TOKEN_PROCESSOR;
	}

	public String makeToken(a) {
		// The length of the randomly generated Token is uncertain
		String token = String.valueOf(System.currentTimeMillis() + new Random().nextInt(99999999));
		try {
			// We want random numbers of the same length, we need to get the data fingerprint
			MessageDigest messageDigest = MessageDigest.getInstance("md5");
			byte[] md5 = messageDigest.digest(token.getBytes());

			// If we return new String(md5), the random number will be garbled
			// Because the random number is arbitrary 01010101010, when converted to a string, will be different from gb2312 code table
			// Gb2312 code table does not necessarily support the binary data, the resulting is garbled
			// Thus, base64 encodes the data as plaintext
			BASE64Encoder base64Encoder = new BASE64Encoder();
			return base64Encoder.encode(md5);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null; }}Copy the code

Create the Token random number and use the getRequestDispatcher to jump to the JSP page (address is still Servlet)

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// Generate a random number
		TokenProcessor tokenProcessor = TokenProcessor.getInstance();
		String token = tokenProcessor.makeToken();

		// Store the random number in Session
		request.getSession().setAttribute("token", token);

		// Go to the display page
		request.getRequestDispatcher("/login3.jsp").forward(request, response);
Copy the code

The Jsp hidden field gets the value of the Session

<form action="/web-01/Mservlet" > <input type="text" name="username"> <input type="submit" value=" submit" id="button" type="hidden" name="token" value="${token}" > </form>Copy the code

In the processing of the form submission page, determine whether the JSP hidden field has a value, whether the value in the Session is empty, and whether the value in the Session and the value in the JSP hidden field are equal

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter printWriter = response.getWriter();
		String serverValue = (String) request.getSession().getAttribute("token");
		String clienValue = request.getParameter("token");

		if(serverValue ! =null&& clienValue ! =null && serverValue.equals(clienValue)) {
			printWriter.write("Processing requests");
			// Clear Session domain object data
			request.getSession().removeAttribute("token");
		} else {
			printWriter.write("Please do not double submit data."); }}Copy the code

The implementation principle is very simple

Store a token in the Session domain

The foreground page’s hidden field then gets the token

At the first visit, we will determine if seesion has a value, and if so, we will compare. Once the comparison is correct, we process the request and delete the data stored in the session

By the time we visit again, our session will have no value, and we will not accept the request from the foreground!

(8) The difference between Session and Cookie

Compare in terms of storage

Cookies can only store strings and encode non-ASCII strings if you want to store them.

A Session can store any type of data. You can think of a Session as a container

In terms of privacy and security

Cookies are stored in the browser and are visible to the client. Information is apt to leak out. If you use cookies, it is best to encrypt them

Sessions are stored on the server and are transparent to the client. No sensitive information was leaked.

In terms of validity

The Cookie is stored in the hard disk. You only need to set the maxAge attribute to a large positive integer. Even if you close the browser, the Cookie will still exist

Session is saved on the server. Set the maxInactiveInterval attribute to determine the validity period of the Session. And the Session relies on a Cookie named JSESSIONID, which has a default maxAge attribute of -1. If you close the browser, the Session doesn’t die off the server, but it dies.

From the burden on the server comparison

Sessions are stored on the server, and each user generates a Session. If there are too many concurrent users, sessions cannot be used, because sessions consume a lot of memory.

Cookies are stored on the client. Does not occupy server resources. Large websites such as Baidu and Sina generally use cookies for session tracking.

Compare in terms of browser support

Cookies are useless if they are disabled by the browser!

If cookies are disabled by the browser, the Session can track sessions through URL rewriting.

Compare across domains

Cookies can set domain properties to implement cross-domain

A Session is valid only in the current domain name and cannot be used across domains

The end:

If there is any shortage in the content, or the wrong place, welcome everyone to give me comments, crab crab everybody! ^_^

If it can help you, then pay attention to me! (The series of articles will be updated on the official account as soon as possible)

Here we do not know each other, but in order to their dreams and efforts

A adhere to push the original Java technology of the public number: the ideal more than twenty days