Welcome to my blog: “Front-end Design and Implementation of micro channel Small Program Login”

A preface.

The purpose of the login/registration design is, of course, to make it robust enough to avoid site-wide blocking as an underlying capability of the application.

At the same time, how to fully consider decoupling and encapsulation, in the development of a new small program, can be faster to reuse capacity, to avoid repeated pit.

Registering for this module is like an iceberg. We think of it as “enter your password and you’re logged in”, but there are all sorts of things to consider below.

Here, to share with you, recently finished a small program login/registration module, precipitation down some design experience and ideas.

2. Service scenarios

In the process of users browsing small programs, businesses often need to obtain some basic information of users, the common ones are:

  1. WeChat nickname
  2. Wechat mobile number

Different products have different requirements on user information and have different authorization procedures.

The first one is common in e-commerce systems. When users purchase goods, in order to identify users’ multi-platform accounts, they often use their mobile phone number to make a contact. At this time, users need to authorize their mobile phone number.

Second, in order to get the basic initialization of user information, it is often necessary to further obtain user information: such as wechat nickname, unionId, etc., user authorization needs to be asked.

The third way, the first way, the second way.

Concept of three.

With the goal of developing a common applet login solution and service, we analyze the business and derive the variables.

Before we do the technical design, a bit of necessary nonsense, basic FM for some concepts.

2.1 About Login

Login is also logged out. To log in, you need to register (or sign up) with an account.

At the beginning of the product is no login/registration function, use more people slowly have. For the sake of the product itself, “users” need to be identified.

In the real society, each of us has an identity ID: ID card. When I was 16 years old, I went to the public security bureau to get my ID card for the first time, and I completed a “registration”. Then I went to Internet cafes to get online, id card brush once, completed a “login” behavior.

For the Internet of the virtual world, this proof of identity is “account number + password”.

Common login/registration methods are:

  1. Account and Password Registration

    In the early days of the Internet, personal email and mobile phone coverage was small. Therefore, users need to think of an account name, we register a QQ number, is this form.

  2. Email Address Registration

    After the turn of the millennium, with the rapid spread of the PC Internet, we all created our own personal email accounts. Plus QQ also bring mailbox account. Due to the privacy of email and the ability to communicate information, most websites start to use email accounts as user names to register, and in the process of registration, they will be required to log in to the corresponding email to check the activation mail and verify our ownership of the registered email.

  3. Registration of mobile phone number

    After the popularization of the Internet, smart phones and mobile Internet have developed rapidly. Mobile phones have become indispensable mobile devices for everyone, and mobile Internet has been deeply integrated into everyone’s modern life. Therefore, compared with email, mobile phone number is more closely related to individuals at present, and more and more mobile applications appear, and the registration method of using mobile phone number as user name is also widely used.

By 2020, wechat will have 1.2 billion users. So wechat accounts, at least in China, have become the “identity mark” of the new Internet world.

And for wechat small program, naturally can know the current user’s wechat account ID. Wechat allows small program applications to “log in” to our small program without the user being aware of it. This is often called “silent login”.

In fact, the login of wechat applets is essentially the same concept as the “single sign-on” of traditional Web applications.

  1. Single sign-on (SSO) : If you log in at site A, sites C and B can achieve rapid “silent login”.
  2. Wechat mini program login: in wechat, login wechat account, then in the whole mini program ecosystem, can achieve “silent login”.

Since Http is stateless, the general approach to login state is as follows:

  1. Cookie-session: used in browser applications
  2. Access Token: Used for non-browser applications such as mobile terminal

In wechat small program, for the “JS logic layer” is not a browser environment, naturally there is no Cookie, then usually use access token.

2.2 About Authorization

For the need to further obtain the user nickname, user phone number and other information of the product. For the sake of users’ privacy, wechat requires users to actively agree to authorize it. Small program application can obtain this part of the information, which has the current popular small program “authorized user information”, “authorized mobile phone number” interaction.

Due to different sensitivities of user information, wechat applets provide “authorization” for different user information in different ways:

  1. Call specific API way, popover authorization.
    1. For example, when wx.getLocation() is called, if the user is not authorized, the address authorization screen is displayed.
    2. If you say no, it won’t pop over again,wx.getLocation()Return failure directly.
  2. <button open-type="xxx" />Way.
    1. Only sensitive user information and user mobile phone number can be obtained by symmetric encryption and decryption with the backend.
    2. The user has refused to click the button again and it will still pop up.
  3. Through wx.authorize(), the authorization is queried in advance so that the authorization does not pop up again when relevant information needs to be obtained later.

4. Detailed design

After sorting out the concept, we can divide the module into two chunks:

  1. The login: is responsible for creating a session with the server, which implements silent login and related fault tolerance, etc., named as:Session
  2. authorization: Responsible for interacting with users, obtaining and updating information, and controlling and processing permissions, etc. The module is named as:Auth

3.1 Implementation of login

3.1.1 Silent Login

The login scheme provided by wechat official can be summarized into three steps:

  1. Front end bywx.login()Get one-time encryption certificate code and hand it to the back end.
  2. The backend transmits this code to the wechat server in exchange for the unique identity of the useropenIdAnd authorization certificatesession_key. (Special API calls for subsequent server-side and wechat server, see:Wechat official document – server access to open data).
  3. The backend transmits the user credentials obtained from the wechat server and the login status credentials (tokens) generated by itself to the front-end. The front end saves it and brings it to the back end on the next request so it can identify which user.

If you just implement the process, it’s pretty easy.

But to implement a robust login process, there are more boundary cases to be aware of:

  1. Wrap up the wx.login() call:

    Wx.login () has unpredictable side effects, such as session_key failure, which can lead to failure in subsequent authorized decryption scenarios. We can provide a method like session.login(), take control of wx.login(), and do a bunch of encapsulation and fault tolerance on it.

  2. Call timing:

    Normally we would initiate a silent login at app launch (app.onlaunch ()). However, there is an asynchronous problem caused by applets lifecycle design issues: when a page is loaded, the asynchronous static login process may not have been completed before calling a back-end API that requires a logon state, causing the request to fail.

    Of course, it is also possible to initiate a login call asynchronously blocking the first time the login interface is called, and this requires a well-designed interface layer.

    Detailed design ideas for the two scenarios mentioned above will be described below.

  3. Problems with concurrent calls:

    In business scenarios, it is inevitable that there will be multiple codes that need to trigger the login, and in extreme cases, these codes will be invoked at the same time. This can result in a short number of times initiating the login process, even though the previous request has not been completed. In this case, we can block the first call and wait for the result of subsequent calls, just like sperm and egg.

  4. Problems with unexpired calls:

    If our login state is not expired, it can be used normally. By default, there is no need to initiate the login process. By default, we can check whether the login state is available, and then initiate a request. You can then provide an argument like session.login({force: true}) to forcibly initiate a login.

3.1.2 Processing asynchronous Status of Silent Login

1. Called when the application starts

Since most situations depend on the login state, it would be natural to make this call when the app is launched (app.onlaunch ()).

But asynchronous blocking is not supported by the App, Page, and Component lifecycle hook functions in the native applet startup process.

Therefore, it is easy for us to encounter that the “login process” initiated by app.onLaunch has not been completed at the time of Page. onLoad, so we cannot properly perform some operations that depend on the login state.

For this situation, we designed a state machine tool: Status

Based on the state machine, we can write code like this:

import { Status } from '@beautywe/plugin-status';

// on app.js
App({
    status: {
       login: new Status('login');
    },

    onLaunch() {
        session
            // Initiate a silent login call
            .login()

            // Set the state machine to SUCCESS
            .then(() = > this.status.login.success())
      
            // Set the state machine to fail
            .catch(() = > this.status.login.fail()); }});// on page.js
Page({
    onLoad() {
      const loginStatus = getApp().status.login;
      
      // Must is used to determine the state, such as waiting for the login, returning if the login succeeds, or throwing if the login fails.
      loginStatus().status.login.must(() = > {
        // Perform some operations that require login state...}); }});Copy the code

2. Initiate login when the first Login interface is invoked

Further, we see that the deeper node that requires a logon state is when the “logon state backend API” is initiated.

We can then initiate “silent login” while calling the “logon required backend API”, and for concurrent scenarios, let the other requests wait.

Using fly.js as the “web request layer” wrapped in wx.request(), we can do a simple example:

// Initiate a request and indicate that the request requires a logon state
fly.post('https://... ', params, { needLogin: true });

// Handle logic in fly interceptor
fly.interceptors.request.use(async (req)=>{

  // When the request requires a logon state
  if(req.needLogin ! = =false) {

    // The ensureLogin core logic is: check whether you are logged in, if not initiate a login call, if you are logged in, enter the queue to wait for the callback.
    await session.ensureLogin();
    
    // After the login succeeds, the token is obtained and sent to the backend using headers.
    const token = await session.getToken();
    Object.assign(req.headers, { [AUTH_KEY_NAME]: token });
  }
  
  return req;
});

Copy the code

3.1.3 User-defined fault tolerance for login state expiration

When the custom login state expires, the backend needs to return a specific status code, such as AUTH_EXPIRED and AUTH_INVALID.

The front-end can listen for the status code of all requests in the “network request layer”, and then initiate a login state refresh, and then replay the failed request:

// Add a response interceptor
fly.interceptors.response.use(
    (response) = > {
      const code = res.data;
        
      // The login state is expired or invalid
      if(['AUTH_EXPIRED'.'AUTH_INVALID'].includes(code) ) {
      
        // Refresh the login state
        await session.refreshLogin();
        
        // Then re-initiate the request
        returnfly.request(request); }})Copy the code

If multiple requests are made concurrently, all of which return a logon invalid status code, the above code will be executed multiple times.

We need to do some special fault tolerance for session.refreshLogin() :

  1. Request lock: Only one in-process network request is allowed at a time.
  2. Wait queue: After a request is locked, all calls to this method are pushed into a queue and shared by the network until the request completes.
  3. Circuit breaker: If it is called several times in a short period of time, it stops responding for a period of time, similar to TCP slow start.

Sample code:

class Session {
  / /...
  
  // Refresh the login fuse, repeat for 3 times at most, then fuse, and recover after 5 seconds
  refreshLoginFuseLine = REFRESH_LOGIN_FUSELINE_DEFAULT;
  refreshLoginFuseLocked = false;
  refreshLoginFuseRestoreTime = 5000;

  // Fuse control
  refreshLoginFuse(): Promise<void> {
    if (this.refreshLoginFuseLocked) {
      return Promise.reject('Refresh login - Fuse has been blown, please wait');
    }
    if (this.refreshLoginFuseLine > 0) {
      this.refreshLoginFuseLine = this.refreshLoginFuseLine - 1;
      return Promise.resolve();
    } else {
      this.refreshLoginFuseLocked = true;
      setTimeout(() = > {
        this.refreshLoginFuseLocked = false;
        this.refreshLoginFuseLine = REFRESH_LOGIN_FUSELINE_DEFAULT;
        logger.info('Refresh login - Fuse disengage');
      }, this.refreshLoginFuseRestoreTime);
      return Promise.reject('Refresh login - fuse blown!! '); }}// And sends back to the callback queue
  refreshLoginQueueMaxLength = 100;
  refreshLoginQueue: any[] = [];
  refreshLoginLocked = false;

  // Refresh the login state
  refreshLogin(): Promise<void> {
    return Promise.resolve()
    
      // Callback queue + fuse control
      .then(() = > this.refreshLoginFuse())
      .then(() = > {
        if (this.refreshLoginLocked) {
          const maxLength = this.refreshLoginQueueMaxLength;
          if (this.refreshLoginQueue.length >= maxLength) {
            return Promise.reject('refreshLoginQueue exceeds capacity:${maxLength}`);
          }
          return new Promise((resolve, reject) = > {
            this.refreshLoginQueue.push([resolve, reject]);
          });
        }
        this.refreshLoginLocked = true;
      })

      // Initiate the login process after passing the front control
      .then(() = > {
        this.clearSession();
        wx.showLoading({ title: 'Refresh in Logon state'.mask: true });
        return this.login()
          .then(() = > {
            wx.hideLoading();
            wx.showToast({ icon: 'none'.title: 'Login successful' });
            this.refreshLoginQueue.forEach(([resolve]) = > resolve());
            this.refreshLoginLocked = false;
          })
          .catch(err= > {
            wx.hideLoading();
            wx.showToast({ icon: 'none'.title: 'Login failed' });
            this.refreshLoginQueue.forEach(([, reject]) = > reject());
            this.refreshLoginLocked = false;
            throw err;
          });
      });

  // ...
}
Copy the code

3.1.4 Fault tolerance of wechat session_key expiration

After the above “silent login”, the wechat server will issue a session_key to the back end, which will be used when we need to obtain wechat open data.

Session_key is time-sensitive. The following is an excerpt from wechat’s official description:

Session key session_key validity

If the developer encounters a signature verification failure or decryption failure due to an incorrect session_key, please pay attention to the following notes related to session_key.

  1. When wx.login is invoked, the user’s session_key may be updated, making the old session_key invalid. (The refresh mechanism has the shortest period. If the same user invokes wx.login several times in a short period, the session_key may not be refreshed every time.) Developers should only call wx.login when it is clear that they need to log back in and update the session_key stored on the server through auth.code2session.
  2. Wechat will not inform developers of the expiry date of session_key. We renew the session_key based on the user’s behavior with the applet. The more frequently users use applets, the longer the session_key validity period.
  3. If the session_key is invalid, the developer can obtain the valid session_key by executing the login process again. The wx.checkSession interface can be used to verify that the session_key is valid, thus avoiding repeated login processes by applets.
  4. When implementing a custom login state, developers can use the session_key validity period as their own login state validity period or implement a custom validity policy.

Translated into two simple sentences:

  1. session_keyTimeliness is controlled by wechat and developers are unpredictable.
  2. wx.loginCould lead tosession_keyExpired and can be used before the interface is used wx.checkSessionCheck it out.

For the second point, we found by experiment that wx.checkSession will return true occasionally when session_key has expired

There is also related feedback from the community that has not been addressed:

  • The small program decrypts the phone number. After a short interval, checkSession: OK, but decryption fails
  • Wx. checkSession is valid but failed to decrypt data
  • CheckSession Checks that the session_key is valid, but fails to decrypt the mobile phone number

So the conclusion is:wx.checkSessionReliability is not 100%.

Based on the above, we need to do some fault tolerance for session_key expiration:

  1. Initiate the need to usesession_keyDo it once before you askwx.checkSessionOperation, refresh login state if failed.
  2. The back-end usingsession_keyFailure to decrypt open data returns a specific error code (e.g.DECRYPT_WX_OPEN_DATA_FAIL), the front end refreshes the login state.

Sample code:

// Define an operation to check the validity of session_key
const ensureSessionKey = async() = > {const hasSession = await new Promise(resolve= > {
    wx.checkSession({
      success: () = > resolve(true),
      fail: () = > resolve(false)}); });if(! hasSession) { logger.info('sessionKey expired, refresh login state ');

    // Follow the refresh logon logic mentioned above
    return session.refreshLogin();
  }

  return Promise.resolve();
}

// Make sure session_key is up to date when making a request (take fly.js as the web request layer example)
const updatePhone = async (params) => {
  await ensureSessionKey();
  const res = await fly.post('https://xxx', params);
}

// Add a response interceptor to listen for network requests to return
fly.interceptors.response.use(
    (response) = > {
      const code = res.data;
        
      // The login state is expired or invalid
      if(['DECRYPT_WX_OPEN_DATA_FAIL'].includes(code)) {

        // Refresh the login state
        await session.refreshLogin();
        
        // Since the encrypted data in the encryption scenario is generated by the user's click, the session_key may have changed, requiring the user to click again.
        wx.showToast({ title: 'Network error, please try again later'.icon: 'none'}); }})Copy the code

3.2 Implementation of Authorization

3.2.1 Component separation and design

In terms of access to user information and mobile phone number, wechat uses to allow users to click authorization.

So to make the code more decoupled, let’s design three components:

  1. <user-contaienr getUserInfo="onUserInfoAuth">: Package click interactive, through<slot>Supports custom UI for click areas.
  2. <phone-container getPhonenNmber="onPhoneAuth">And:<user-container>In the same way.
  3. <auth-flow>: Combination based on service requirements<user-container>,<phone-container>Combination to define different authorization processes.

Take the process for the opening business scenario, which has the following requirements:

  1. There are multiple steps.
  2. If it breaks in the middle, it can be used indirectly.
  3. In some scenarios, only User information authorization is required, but mobile phone number is not required.

Then the authorization stage can be divided into three layers:

// The user login stage
export enum AuthStep {
  // Phase 1: Only login state, no user information, no mobile phone number
  ONE = 1.// Phase 2: there is user information, but no mobile phone number
  TWO = 2.// Stage 3: There is user information, there is mobile phone number
  THREE = 3,}Copy the code

The AuthStep progression is irreversible, and we can define a nextStep function to encapsulate the AuthStep update logic. For external use, just mindlessly call the nextStep method and wait for the callback result.

Sample pseudocode:

// auth-flow component

Component({
  // ...
  
  data: {
    // By default, only phase two needs to be reached.
    mustAuthStep: AuthStep.TWO
  },
  
  // The phase that needs to be reached to allow temporary changes to components.
  setMustAuthStep(mustAuthStep: AuthStep) {
    this.setData({ mustAuthStep });
  },
  
  // Based on the user's current information, calculate that the user is in the authorization phase
  getAuthStep() {
    let currAuthStep;
    
    // No user information, still in the first step
    if(! session.hasUser() || ! session.hasUnionId()) { currAuthStep = AuthStepType.ONE; }// No cell phone number, still in step 2
    if(! session.hasPhone()) { currAuthStep = AuthStepType.TWO; }// Both, in step 3
    currAuthStep = AuthStepType.THREE;
    return currAuthStep;
  }
  
  // Initiate the next authorization, if all completed, return success.
  nextStep(e) {
    const { mustAuthStep } = this.data;
    const currAuthStep = this.updateAuthStep();
  
    // Authorization is complete
    if (currAuthStep >= mustAuthStep || currAuthStep === AuthStepType.THREE) {
      // Update the global authorization state machine, broadcast messages to subscribers.
      return getApp().status.auth.success();
    }

    // Step 1: Update user information
    if (currAuthStep === AuthStepType.ONE) {
      // The ciphertext information is available
      if (e) session.updateUser(e);

      // Update to view layer, display corresponding UI, wait to obtain user information
      else this.setData({ currAuthStep });
      return;
    }

    // Step 2: Update your mobile phone information
    if (currAuthStep === AuthStepType.TWO) {
      // There is ciphertext information, and the mobile number is updated
      if (e) this.bindPhone(e);

      // No ciphertext message is displayed
      else this.setData({ currAuthStep });
      return;
    }

    console.warn('auth. NextStep mistakes', { currAuthStep, mustAuthStep });
  },
  
  // ...
});
Copy the code

So our

can make different UI presentations based on currAuthStep and mustAuthStep. Note that the nextStep(e) function is connected when using

and .

Sample pseudocode:

<view class="auth-flow">

  <! -- Authorization completed -->
  <block wx:if="{{currAuthStep === mustAuthStep || currAuthStep === AuthStep.THREE}}">
    <view>Authorization completed</view>
  </block>

  <! -- Not authorized, first step: authorized user information -->
  <block wx:elif="{{currAuthStep === AuthStep.ONE}}">
    <user-container bind:getuserinfo="nextStep">
      <view>Authorized User Information</view>
    </user-container>
  </block>

  <! -- Not authorized, step 2: Authorized mobile phone number -->
  <block wx:elif="{{currAuthStep === AuthStep.TWO}}">
    <phone-container bind:getphonenumber="nextStep">
      <view>Authorized Mobile phone Number</view>
    </phone-container>
  </block>
  
</view>
Copy the code

3.2.2 Processing of permission interception

At this point, we have the component < auth-Flow > that is used to host the authorization process, so it is time to decide when to use it.

Let’s comb through the scenarios that require authorization:

  1. Click a button, for example, to buy an item.

    In this scenario, authorization is usually done through a pop-up window, which the user can choose to disable.

  2. View a page, for example, visit the personal Center.

    For this scenario, we can intercept and pop-up when clicking to jump to a page. But such a disadvantage is that the jump to the target page may be a lot of places, each intercept, inevitably will be wrong. And when the target page as a “small program landing page”, it can not be avoided.

    At this point, we can complete the authorization process by redirecting to the authorization page, and then come back.

So we define an enumeration variable:

// Display of authorization
export enum AuthDisplayMode {
  // in popover form
  POPUP = 'button'.// in page form
  PAGE = 'page',}Copy the code

We could design a mustAuth method that controls authorization when a button is clicked or when a page loads.

Examples of pseudocode:

class Session {
  // ...
  
  mustAuth({
    mustAuthStep = AuthStepType.TWO, // LEVEL that requires authorization. By default, user information needs to be obtained
    popupCompName = 'auth-popup'.// Authorize the id of the popover component
    mode = AuthDisplayMode.POPUP, // Defaults to popover mode} = {}) :Promise<void> {
    
    // If the current authorization step reached the standard, success is returned
    if (this.currentAuthStep() >= mustAuthStep) return Promise.resolve();

    // Try to get the 
       component instance of the current page
    const pages = getCurrentPages();
    const curPage = pages[pages.length - 1];
    const popupComp = curPage.selectComponent(` #${popupCompName}`);

    // The component does not exist or the specified page is displayed, jump to the authorization page
    if(! popupComp || mode === AuthDisplayMode.PAGE) {const curRoute = curPage.route;

      // Go to the authorization page, add the route to the current page, and return to the current page after the authorization is complete.
      wx.redirectTo({ url: `authPage? backTo=The ${encodeURIComponent(curRoute)}` });
      return Promise.resolve();
    }
    
    // Set the authorization LEVEL, and then call the nextStep method of 
      
        for further authorization.
      
    popupComp.setMustAuthStep(mustAuthStep);
    popupComp.nextStep();

    // Wait for a successful callback or a failed callback
    return new Promise((resolve, reject) = > {
      const authStatus = getApp().status.auth;
      authStatus.onceSuccess(resolve);
      authStatus.onceFail(reject);
    });
  }
  
  // ...
}
Copy the code

Then we can intercept authorization when a button is clicked, or when a page is loaded:

Page({
  onLoad() {
    session.mustAuth().then(() = > {
      // Start the initialization page...
    });
  }
  
  onClick(e) {
    session.mustAuth().then(() = > {
      // Start processing the callback logic...}); }})Copy the code

Of course, if the project uses TS or supports the ES7 Decorator feature, we can provide a Decorator version for mustAuth:

export function mustAuth(option = {}) {
  return function(_target, _propertyName, descriptor,) {
    // Hijack the target method
    const method = descriptor.value;
    
    // Override the target method
    descriptor.value = function(. args: any[]) {
      return session.mustAuth(option).then(() = > {
        // After login, replay the original method
        if (method) return method.apply(this, args);
      });
    };
  };
}
Copy the code

Then the way to use it is simpler:

Page({
  @mustAuth();
  onLoad() {
    // Start the initialization page...
  }
  
  @mustAuth();
  onClick(e) {
    // Start processing the callback logic...}});Copy the code

3.3. Sorting out front-end and back-end interaction protocols

As a reusable applet login scheme, it is necessary to define the front and back end interaction protocols.

Then the whole login process, the need for the interface is as follows:

  1. SilentLogin silentLogin

    1. The arguments:
      1. Code: from wx. The login ()
    2. Reference:
      1. Token: user-defined login status certificate
      2. UserInfo: indicates the user information
    3. Description:
      1. The back end uses code to exchange the user id with the wechat client, and then registers and logs in the user, returning to the custom login statetokenTo the front
      2. tokenThe front end stores it and takes it with every request
      3. UserInfo must be includednicknameandphoneField, the front end is used to calculate the authorization phase of the current user. Of course the recording of this state can be put in the back end, but we think it’s more flexible to put it in the front end.
  2. UpdateUser information updateUser

    1. The arguments:
      1. Nickname: nickname of the user
      2. Encrypt: Wechat open data relatediv.encryptedData
      3. And other non-essential fields such as gender and address
    2. Reference:
      1. UserInfo: indicates the updated user information
    3. Description:
      1. The backend decrypts wechat open data and obtains hidden data, such as:unionId Etc.
      2. Backend support updates includenicknameAnd other basic user information.
      3. The front end updates the userInfo information tosessionIs used to calculate the authorization phase.
  3. Update the user’s mobile phone number updatePhone

    1. The arguments:
      1. Encrypt: Wechat open data relatediv.encryptedData
    2. Reference:
      1. UserInfo: indicates the updated user information
    3. Description:
      1. The backend decrypts the open office, obtains the mobile phone number, and updates it to the user information.
      2. The front end updates the userInfo information tosessionIs used to calculate the authorization phase.
  4. Unbind the phone number unbindPhone

    1. The ginseng: –
    2. Participation: –
    3. Note: If the user’s mobile phone number is unbound successfully, use the protocol defined by the service.
  5. Login logout

    1. The ginseng: –

    2. Participation: –

    3. Note: The back-end active expired login state, successful or not, go to the service defined protocol.

5. Structure diagram

Finally, let’s comb through the overall “login service” architecture diagram:

The generic service provided by the combination of “login service” and “underlying construction”, the business layer only needs to customize the authorization flow

according to the product requirements, which can satisfy most scenarios.

6. Summary

This article expands through some common login authorization scenarios to describe the details.

The concepts of “login” and “authorization” are sorted out.

Then it introduces some key technologies for “login” :

  1. Silent login
  2. Processing the asynchronous status of silent login
  3. Custom fault tolerant handling of login state expiration
  4. WeChatsession_keyExpired fault tolerant handling

For “authorization”, there is logic to design the UI part, which also involves component splitting:

  1. Component separation and design
  2. Processing of permission interception

Then, the back-end interfaces that the login authorization scheme depends on are sorted out, and the simplest reference protocol is given.

Finally, from the point of view of “aiming at settling a common applet login solution and service”, we combed the layers of architecture.

  1. Business Customization layer
  2. Login service layer
  3. Construction of the underlying

Reference 7.

  1. Fly. Js’s official website
  2. Wechat official document – Authorization
  3. Wechat official document – server access to open data
  4. Official wechat community
    1. The small program decrypts the phone number. After a short interval, checkSession: OK, but decryption fails
    2. Wx. checkSession is valid but failed to decrypt data
    3. CheckSession Checks that the session_key is valid, but fails to decrypt the mobile phone number

Eight open source.

In response to the needs of your audience, these dynamics led me to “step forward” and encapsulate some reusable solutions:

  1. Concurrent processing: Method Fuse – Function Fuse
  2. A Concurrent Merger – a Concurrent Merger is called