preface

In learning Javaweb, we have been stressed that there are four scopes in Javaweb: pageContext, Request, Session, and Application.

  • The pageContext domainThe variables in the page are available only on the current page.
  • Request the domainThe valid scope of the object in is the current request scope.
  • The session domainThe valid scope of the object in is the current session scope.
  • The application domainThe effective range of the object in is where the entire application is active.

After understanding the basic concepts, we can conclude that in order to conduct network communication, we generally use request and session. Since the scope of the request is only valid within the scope of the request, the data is automatically destroyed after each request. However, sometimes we want to store some long-lived data, such as login information, user information, etc., which the request domain cannot do.

A server session and a client (browser) cookie are similar in nature, for example, they can store data for a certain period of time. If the Cookie mechanism is the “pass” on the client, then the Session mechanism is the “customer list” composed of multiple “passes”. “In theory, these two memories are unrelated. But because of their similar nature, Java JSPS, Spring’s Thymeleaf template, link them together. Making people create sessions and cookies is consistent.” Take JSP for example, JSP is a special servlet program, although we write HTML statements in it, but it is actually a servlet by some means to turn into a front-end page. The Spring and Thymeleaf templates also use this approach. Because sessions can store long-lived data, we can use sessions to store login information, user information, etc.

Session /cookie disadvantages:

  • cookieIt’s not very secure. Someone can analyze it and store it locallycookieAnd carry oncookieDeception.
  • A singlecookieThe limitation on the client side is3KThat is, a site is hosted on the clientcookieNo more than3k.
  • sessionIt will be stored on the server for a certain amount of time. When the volume of traffic, will take up the performance of the server.
  • If it is in a server cluster or a cross-domain service-oriented architecture, it is requiredsessionData sharing in a domain, that is, each server can read itsession. At this point, we’ll just have tosessionData persistence, which is a very bad idea.

Bigger questions

If the user disables cookies in the browser Settings; Or your site is implemented using a technology that separates the front from the back. There’s no simple way to use a session. On the one hand, your data cannot be stored because there is no cookie in the browser. On the other hand, the connection between the front and back ends is torn, and the session set separately on the server cannot be synchronized to the cookie of the browser. At this point, we need to use another idea: open up a space on both the front and back end to store user information.

Tokens are such an idea. The process is as follows:

  1. The client requests login using the username and password.
  2. The server receives a request to verify the user name and password.
  3. After successful validation, the server regenerates a unique string (TokenToken), and saves the token in the server’s cache, and sends the token to the client.
  4. The client receivesTokenYou can store it later, like inCookieOr in theLocalStorageIn the water.
  5. Each time a client requests a resource from the server, it must carry the resource signed by the serverToken.
  6. The server receives the request and then validates the client with the requestTokenIf the validation succeeds, the requested data is returned to the client.

The benefits of token

In addition, token can not only solve this practical problem, but also bring many benefits.

  1. Stateless and extensible: Stored on the client sidetokensIs stateless and extensible. Based on this statelessness and no storagesessionInformation, the load balancer can transfer user information from one server to another.
  2. Security: send in requesttokenInstead of sending itcookieCan preventCSRFCross-site request forgery. Even on the client sidecookiestoragetoken.cookieIt is only a storage mechanism and is not used for authentication. andtokenThere is a time limit, after a period of time the user needs to re-authenticate.
  3. Scalability: Ability to share data with other programs.
  4. Multi-platform cross-domain: each time the server is accessed with a token bound to its own information. In the service cluster environment, instead of accessing a specific server, the server is selected for processing by taking out data from the cache server and using a load balancer.

The realization of the Token

Preparation stage

  1. useMysqlThe database
  2. openRedisThe cache
  3. useSpringbootThe framework

Code segment

1. Login

<form id="login_form" class="login_form">

User name:<input type="text" name="username">

    <br>

Password:<input type="password" name="password">

    <br>

    <input type="button" value="Submit" onclick="login()">

</form>

<script type="application/javascript">

    function login(){

        $.ajax({

            type:"post"./ / post request

            dataType:"json".// Returns the json format

            url:"http://localhost:8080/login".// Request path

            data: $("#login_form").serialize(),     // Form serialization

            successfunction(result){

                console.log(result)                // Print the result

                if(result.code == 200) {

                    / / store token

                    localStorage.token = result.data;     // Save the token to localStorage

                    location.href = "/index";           // Jump to the home page

                }

            },fail:function(err){

                console.log(err)

            }

        });

    }

</script>

Copy the code
@Resource

RedisTemplate<String, Object> redisTemplate;       // Redis cache templates



@RequestMapping(value = "/login", method = RequestMethod.POST)

@ResponseBody

public Result login(String username, String password){

    System.out.println(username);

    System.out.println(password);

    User user = userService.getUser(username, password);

    if(user ! =null) {

        // The login succeeds, and the token is generated

        String token = UUID.randomUUID() + "";     // Generate a unique key using a UUID as a token

        redisTemplate.opsForValue().set(token, user, Duration.ofMinutes(30L));    // Put the token in redis cache for half an hour

        return new Result(200."Request successful", token);

    }

    return new Result(400."Request failed".null);

}

Copy the code

2. Resource access request

function requestToken(){

    $.ajax({

        type:"get".// Request mode

        dataType"json".// Return the format

        url:"http://localhost:8080/getUser".// Request an address

        headers : {

            "token" : localStorage.token        // Set the header. It is safer to put the token in the request header

        },

        success:function(result){

            console.log(result)

        }

    })

}

Copy the code
@RequestMapping("/getUser")

@ResponseBody

public Result getUserOfLogin(HttpServletRequest request){

    String token = request.getHeader("token");   // Get the token from the request header

    Object user = redisTemplate.opsForValue().get(token);   // Search the redis cache for the token



    if(user ! =null) {

        // Get success, encapsulate return value

        return new Result(200."Request successful", user);

    }

    return new Result(400."Could not find user information".null);    // The token may not exist or the token may have expired

}

Copy the code

3. Log out

function logout(){

    $.ajax({

        type:"get".

        url:"http://localhost:8080/logout".

        dataType:"json".

        headers: {

            "token":localStorage.token

        },

        success:function(result){

            localStorage.removeItem("token");   // Clear the token on the browser side

        },fail : function(err){

            console.log(err)

        }

    })

}

Copy the code
@RequestMapping("/logout")

@ResponseBody

public Result logout(HttpServletRequest request){

    String token = request.getHeader("token");     // Get the token from the request header

    Boolean delete = redisTemplate.delete(token);   // Delete the information in redis cache according to the token

    if(delete){

        return new Result(200."Logout successful".null);

    }else{

        return new Result(400."Logout failed".null);



    }

}

Copy the code