JSON WEB TOKEN (JWT) is one of the most commonly used verification methods.

His role is as follows

  • JWT is an open JSON-based standard implemented to deliver declarations in network application environments.
  • JWT is used to pass authenticated user identity information between the identity provider and the service provider, in short, using
  • A means to verify identity, such as login verification, like the cookie we used earlier.
  • JWT can use HMAC algorithm or RSA public and private key pair for signature to ensure information reliability.

Application scenarios

In a scenario such as authentication, once a user is logged in, each subsequent request contains JWT for authentication information. As the communication parties use JWT to encode the data, its information is signed, so it can ensure the security of the information.

JWT contrast cookies

Cookie shortcomings

  • The client sends a request to the server. After the server plants cookies, each request will bring cookies, wasting bandwidth
  • Cookies cannot be accessed across servers and are not supported across domains
  • The server needs to store logged user objects, wasting server memory

JWT advantages

  • JWT is not state-based, so you do not need to carry tokens with each request to save traffic
  • The server takes no memory and the information is relatively reliable
  • It can be shared across servers

That’s what the industry says about JWT, but is it really like that?

So let’s see how JWT is generated, right? JWT is a specification. It is constructed from one of the following structures.

header.payload.signature
Copy the code

The Header section of JWT contains information about how to calculate the JWT signature, and is a JSON object of the following form:

{
    "typ": "JWT"."alg": "HS256"
}
Copy the code

In the JSON above, the value of the “TYp” key specifies that the object is JWT, and the value of the “alg” key specifies the algorithm used to create the JWT signature. In the example, we use the HMAC-SHA256 algorithm, a hashing algorithm that uses a key, to compute the signature (more on that in Step 3).

Create a content

The payload part of the JWT is the data stored in the JWT. In our example, the authentication server creates a JWT that stores user information, specifically the user ID.

{
    "userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}
Copy the code

In our example, we put only one declaration into payload. You can add as many declarations as you need. JWT specifies seven official fields to choose from.

Iss (Issuer) : exp (expiration time) : expiration time sub (subject) : aud (audience) : NBF (Not Before) : iAT (Issued At) : Issue time JTI (JWT ID) : numberCopy the code

Create a SIGNATURE

// Signature Algorithm data = base64urlEncode(header) + ". + base64urlEncode( payload ) hashedData =hash( data, secret )
signature = base64urlEncode( hashedData )
Copy the code

Yes, JWT is verified by continuous calculation.

In this case, the performance problem refers to the problem of increasing the number of requests caused by this structure. In the JWT usage scenario, all requests need to be complete with JWT data. Payload data is only base64 data and is not processed. Therefore, if you add too much data to the payload, the structure of the JWT becomes larger and the request becomes less efficient.

Storing tokens in Redie or mongodb is also a good option. How do we do that?

I’m going to start with Laravel

Migrate the files as follows

            $table->bigIncrements('id');
            $table->integer('user_id');
            $table->string('token', 191)->default(' ')->comment('token');
            $table->integer('expiry_time')->default(0)->comment('Due Time');
            $table->string('ua')->default(' ')->comment('browser');
            $table->string('ip')->default(' ')->comment('User IP');
            $table->timestamps();
Copy the code

The Token is generated when the login verification succeeds

        $token = md5(uniqid(md5(microtime(true)), true));
        $token = sha1($token);

        UserTokens::create([
            'user_id'= >$user->id,
            'token'= >$token.'ip' => request()->ip(),
            'expiry_time' => time() + 2 * 60 * 60,
            'ua' => request()->userAgent()
        ]);

        return $token;
Copy the code

Inject middleware interceptors where needed

class Authenticate extends Controller
{
    public function handle(Request $request, \Closure $next)
    {
        $Authorization = $request->header('Authorization');

        if (!$Authorization) {
            return response($this->error('Please log in', 40001));
        }

        $token = explode(' '.$Authorization);
        $token = $token[1].if ($this->validateToken($token)) {
            return $this->validateToken($token);
        }

        return $next($request);
    }

    protected function validateToken($token)
    {
        $dbToken = UserTokens::where('token'.$token)->first();
        if ($dbToken->token ! =$token) {
            return response($this->error('Your information is wrong! ', 40010));
        } else if ($dbToken->expiry_time < time()) {
            return response($this->error('Token validity expires', 40020));
        } else if ($dbToken->ua ! = \request()->userAgent()) {return response($this->error('Your information is wrong! ', 40010));
        } else if ($dbToken->ip ! = \request()->ip()) {return response($this->error('Your information is wrong! ', 40010));
        } else {
            return false; }}}Copy the code

This is also possible.