Private toolset 7 -- Token timeliness verification in webapi

Confucius said: if a worker wants to do well, he must sharpen his tools first

github: https://github.com/redAntCpp/CSharpTools

Next to the previous article, the previous article only realizes the generation and parsing of token, and incidentally mentions the verification mechanism. However, in actual business, it is usually necessary to verify the timeliness of the token. Just like going to a movie, the movie ticket is valid on the same day and must be used within the validity period, otherwise you need to buy a new ticket.

token aging verification

General idea

In the first step, there is a code:

 if (isAPIUser(UserName, PassWord))
                    {
                       //The validity period should be verified here. It has not been written for the time being, and ideas will be provided later
                        return true;
                    }

Time effective verification should be added here. So how to realize the timeliness verification of token? Here are two ideas:

Train of thought 1

  1. Set a validity period so that each time the client invokes the service, it will take the timestamp (encryption) of the first token obtained.
  2. After the server gets this time, it decrypts it, adds the validity period, and compares the time of the current server. If it is greater than, it is valid, and if it is less than, it is invalid,

Add this paragraph to IsAuthorized

string requestTime = httpContext.Request.Headers["rtime"]; //The request time is signed by DESC, and the header file
          if (string.IsNullOrEmpty(requestTime))return false;
            DateTime Requestdt = DateTime.Parse(Decrypt.RSADecrypt(PrivateKey,requestTime)).AddMinutes(int.Parse(TimeStamp));
            DateTime Newdt = DateTime.Now; //The current time the server received the request
            if (Requestdt < Newdt) //The token has expired
            {
                ErrorMessage = "token Expired, please get it again";
                return false;
           }

Train of thought 2

  1. When the client obtains the token, the server records the time of obtaining the token and the user.
  2. Whenever the customer uses the service to enter the verification phase, take out the time and user id in step 1 and add the validity period.
  3. Determine the time after adding the validity period and the time size of the server.

The difference between the two ideas lies in who records the token time. Of course, the security must be that idea 2 is safer. Because if the customer does not transmit the time as required, the server cannot verify it. But idea 2 also has disadvantages. It records the user's token every time, which consumes a lot of storage space, and the query speed will also affect the token verification speed. If it is stored on the database, the network speed of connecting to the database is also a problem to be considered.
Both methods have advantages and disadvantages.
Now let's share an improved method of my idea 2. Use sqlite to store token s. For sqlite reference: Private toolset 5 - C# database operation class (DBHelper)
sqlite can be stored locally without considering network problems, and has simple structure and small volume. It is very suitable for this kind of log recording.

realization

  1. Create SQLite local table, T_APIUser is used to record user information. The field reference is as follows:
  2. Create local table_ Tokentrace is used to record the generation time and status of the token.
  3. In the filter, modify the judgment logic. If the user passes the authentication, get the last time the user obtains the token, add the validity period, and compare it with the current time.
                    if (APIUserID != -1)
                    {
                        //Validation validity
                        string TokenCreateTime = getTokenCreateTime(APIUserID);
                        DateTime Requestdt = DateTime.Parse(TokenCreateTime).AddMinutes(int.Parse(TimeStamp));
                        if (Requestdt < DateTime.Now)
                        {
                            ErrorMessage = "token Expired, please get it again";
                            return false;
                        }
                        else
                        {

                            return true;
                        }
                    }


  1. . here is the supplementary method:
 //Auxiliary method
        
        //Verify account and password
        private int isAPIUser(string UserNo, string PassWord)
        {
            Log.AddInfo("APIFilter.isAPIUser()", "Begin");
            string sqlstr = "SELECT APIUserID FROM T_APIUser where UserNo = @UserNo and PassWord = @PassWord";
            SQLiteParameter[] par = {
                new SQLiteParameter("@UserNo", UserNo),
                new SQLiteParameter("@PassWord",PassWord)
            };
            DataSet qry = site.SelectData(sqlstr, par);
            if (qry.Tables.Count == 1 && qry.Tables[0].Rows.Count == 0)
            {
                Log.AddError("APIFilter.isAPIUser()", "APIUser Account does not exist");
                return -1;
            }
            else
            {
                Log.AddInfo("APIFilter.isAPIUser()", "End");
                return Convert.ToInt32(qry.Tables[0].Rows[0]["APIUserID"].ToString());
            }
        }

        private string getTokenCreateTime(int APIUserID)
        {
            string sqlStr = "SELECT CreateTime FROM T_TokenTrace where APIUserID = @APIUserID ORDER BY TokenTraceID  DESC LIMIT 1";
            SQLiteParameter[] par = {
                new SQLiteParameter("@APIUserID", APIUserID),
            };
            DataSet qry = site.SelectData(sqlStr, par);
            return qry.Tables[0].Rows[0]["CreateTime"].ToString();
        }

In this way, the validity verification of token can be easily realized.

Practical drill

  1. Get token interface
  2. In the original token controller, add an interface for testing and our filter, and the program will execute downward in order.
  3. Set the validity period to 2 minutes. What I read here is the configuration in json:
  4. Verify whether the interface can be accessed normally within the validity period of the token:
  5. Call this interface again after 2 minutes:

Other expansion

The token is usually different every time. The value of the token is related to the encrypted key. Different keys will produce different tokens. Therefore, if you want to get different tokens every time, we can randomly generate a string as the key when configuring the key to ensure the randomness of the token. To achieve this function, it is not appropriate to write in the configuration file, because the configuration file is usually not modified.
There will be no further discussion here.

Keywords: ASP.NET C# server http token

Added by shah on Sat, 19 Feb 2022 17:44:55 +0200