Start with the login and registration process:

1. Android login looks like this:
loginData.put("name", userNameText.toString());
loginData.put("password", passWordText.toString());
loginData.put("platform"."android");
// Synchronization mode
try {
    // Invoke the login interface network request
    JSONObject response = okHttpManager.post(login_url, loginData);Copy the code
2. Record the following information when the client successfully logs in
/ / save the user information, the commonly used single save PreferenceManager PM = PreferenceManager. GetInstance (); pm.setString("user_id", loginDetail.getString("user_id"));
pm.setString("app_token", loginDetail.getString("app_token"));
pm.setString("app_ticket", loginDetail.getString("ticket"));
pm.setString("userinfo", loginDetail.toString());Copy the code

So how do we get the app_token and ticket returned from the server and what does that do? ????

3. After receiving the login information, the server performs the following operations:
/ / token is generated
$app_token  = empty($userInfo['app_token'])?$this->genAppToken($retParams['name'], $retParams['platform') :' ';Copy the code

At this point, the APP_token field in the Users table is updated.

//生成ticket
$ticket = $this->genAppToken($userInfo['user_id'], $userInfo['mobile']);Copy the code

Select * from online_user; select * from online_user; select * from online_user;

id user_id ticket expire_time platform

(The purpose of this table is to record successful login (i.e. online table), if logged out should be deleted.)

Add (userID and ticket) to index (userID and ticket).

The genAppToken can be md5 or SHA, or one-way encryption. In this case, API interface signature verification can be performed

Client-side logic is similar to server-side logic

The server side is as follows:

In terms of API, it is necessary to distinguish whether the interface for login is needed, so verification judgment should be exempted: The following can be achieved

$loginArr  = array('login'.'register'.'mobile_verifycode_login'.'forget_password'.'send_email'.'createSMS'.'check_exis ts'.'notifySync'.'wx_auth_register'.'wx_auth_login');
 60             if(! in_array($method, $loginArr)) {61                 $this->load->model(array('User_model'));
 62                 $operator      = $this->isLogin();
 63                 $this->operator = array(
 64                     'user_id' => (int)$operator['user_id'].'ticket' => $operator['ticket']
 65                 );
 66             }Copy the code

If a user is logged in, the user’s user_id or ticket can be used to determine whether the user is logged in. If the user is not logged in, the user will jump to the login page

In interface-free authentication, it is obvious that ticket cannot be used to distinguish users, so we use sign signature to solve some problems of API signature

  • Whether the request parameters were tampered with
  • Whether the source of the request is legitimate
  • Whether the request is unique

Therefore, the signing policy can be as follows:

$sign  = $params['sign'];
269         $timestamp  = $params['fx_timestamp'];
270$secret ="123Sqweqweq ";// Use your own secret
271


272         $app_ticket = $this->input->get_post(COOKIE_TICKET);
273         $app_token  = ' ';
274         if (!empty($app_ticket)) {
275             / / get app_token
276             $cacheData  = $this->ciredis->hGetAll('online:ticket:' . $app_ticket);
277             $userInfo  = $this->User_model->get(array('user_id' => $cacheData['user_id']));
278             $app_token = !empty($userInfo['app_token'])? $userInfo['app_token'] : APPSECRET;
279         }Copy the code

When the client sends parameters to the server, determine whether app_ticket is sent. If yes, use the app_ticket to add app_token to the table or cache. (Note that app_ticket and App_token cannot be placed in the same cache or table. User_id is still required.

// filter out sign
285         unset($params['sign'], $params['s']);
286         / / sorting
287         ksort($params);
288         reset($params);
289
290         // Concatenates a string
291         $arg = "";
292         while (list ($key, $val) = each($params)) {
293             $arg .= $key . "=" . $val . "&";
294         }
295         $arg    = rtrim($arg,'&');Copy the code

First save the signature passed by the user, the server needs to use its own method to generate the signature, and then match the signature transmitted by the client, if it succeeds, it will pass, otherwise it will report a signature error

In general, server-side signature verification steps are as follows:

1. Sort ksort first

2. The string concatenation foreach ($params as $key = > $val) {$arg. = $key. “=”. $val. “&”; }

3. Add a random number to the concatenated string for MD5 or SHA signature, similar to the following:

Key ="123Aqwqw";$newSign = sha1 ($arg. "$key");Copy the code

The resulting newSign is the sign generated by the server (the signed string can be longer and more complex).

Then this newSign will match the sign sent by the client. If the same, pass.

The benefits of this are as follows:

NewSign is encrypted according to the parameters passed so when someone else changes the parameters, the newSign generated by the server must be different from the sign passed by the client, the signature doesn’t match and then somebody says == if I hijack the code on the client and get the signer on the client, You can change the client’s sign. = =

This is true, so Android often makes == write a checkmark process in JNI and C ==. This code cannot be obtained by decompilation (== this code is compiled into the so file ==), so the client code is guaranteed to be safe

The client code is as follows:

secret  = PreferenceManager.getInstance().getString("app_token");
ShowLog.e(url);
addTicketToParams(params);
buildSign(params);Copy the code

Add ticket and sign at the place of network request (the network request must be made into == public call ==, so as to realize unified interface access, which can be made into singleton mode.)

Secret is used to obtain the app_token saved during login. AddTicketToParams is used to addTicketToParams, which is also the ticket saved during login

Focus on the part where ==buidlSign==.

params.put("timestamp", Long.toString(timestamp));
params.put("appsecret", secret);

Map<String.String> sortedParams        = new TreeMap<String.String>(params);
Set<Map.Entry<String.String>> entries  = sortedParams.entrySet();

StringBuffer buffer = new StringBuffer();
byte[] bytes    = null;
try {
    for (Map.Entry<String.String> entry : entries) {
        if (buffer.length() > 0) {
            buffer.append("&");
        }

        buffer.append(entry.getKey()).append("=").append(entry.getValue());Copy the code

Get the timestamp and get the secret which was app_token and then do the same as the server side and add = and & one by one and then add jNI’s c program to add parameters which is similar to the server side logic but using C to achieve the server-side PHP language implementation effect The string sign is returned, and then

arams.remove("appsecret");
ShowLog.e(params.toString());
params.put("sign", doencrypt(buffer.toString()));
ShowLog.e(params.get("sign"));Copy the code

Add this string to sign and interact with the server side

This is the entire API interface signature verification process.

This note is that whether need to validate or from interface Must let app_ticket and app_token come in pairs (either Or don’t) article source: www.pengge.win/Index/Blog/…