WeChat applet silent login and maintenance of custom login state detailed explanation

WeChat applet silent login and maintenance of custom login state detailed explanation

1. Background

In a mini program, openid is a user's identifier for a mini program/public account. Developers can identify the user through this identifier, just like your ID card.

2. What is silent login?

In common applications, users log in through form authentication to establish a user system. This common login method is generally through the login page form, which is noticeable to users.

In the mini program, since it is based on WeChat, we can use the API capabilities officially provided by WeChat to enable us to obtain the user identity (openid) unconsciously and quickly establish a user system within the mini program. This is imperceptible to the user, so the program completes the automatic login process.

2.1 Login process sequence

The following picture is taken from WeChat official

The applet calls wx.login() to get the code and upload it to the server

export async function doLogin() {
 if (isLogin) return false
 isLogin = true
 removeCache('token')
 const { code } = await wxp.login()
 const data = await login({ code })
 setCache('token', data.data.token)
 isLogin = false
 return true
}

The server gets the code and calls the auth.code2Session interface to exchange for openid
const getOpenid = async function (appid, secret, code) {
    const resData = await axios.get('https://api.weixin.qq.com/sns/jscode2session?appid=' + appid + '&secret=' + secret + '&js_code=' + code + '&grant_type=authorization_code');
    return resData.data;
}

Summarize the process:

  • The applet calls wx.login() to get the code and upload it to the server
  • The server uses the code and calls the WeChat auth.code2Session interface to exchange for openid
  • The backend server generates a custom token based on the openid and returns it to the frontend and stores it. Subsequent business logic uses the token to identify the user

3. How to maintain a custom login state

Let's take a look at the official approach:

wx.checkSession({
  success () {
    //session_key has not expired and is valid throughout this life cycle},
  fail () {
    //session_key has expired, you need to re-execute the login process wx.login() //Re-login}
})

From the figure we can see that it is WeChat's checkSession interface that really determines the login state. Therefore, each time you check whether the user login status is valid, you first call a checkSession interface. If the session_key is invalid, then initiate the login process.

4. Overall process of silent login

4.1 Login initiated in app.onLaunch

Since most of the API calls require token verification, it is most appropriate to initiate silent login in the periodic function app.onLaunch when the mini program is started.

4.2 Processing applet does not support asynchronous blocking

Because the page-level and component-level lifecycle functions do not support asynchronous blocking in the startup process of the mini program, a situation may occur where the page-level lifecycle function has already initiated a request to the server before the wx.login initiated in app.onLaunch succeeds. Since most of our interface designs require verification, the login has not been successful at this time, and the token has not been returned correctly, so the data acquisition interface initiated by the page-level life cycle will definitely report an error (for example, 401 is returned)

4.2.1 Rough Solution

Using callback function

//app.js
this.globalData.wxp.showLoading({
        title: 'Logging in...'
      });
      await login();
      this.globalData.hasLogin = true;
      if (this.checkLoginReadyCallback) {
        this.checkLoginReadyCallback();
      }
      this.globalData.wxp.hideLoading();
      
In the life cycle of the page async onLoad() {
    if (app.globalData.hasLogin) {
    //If you are already logged in, get the data directly this.getUserInfo();
      this.getEvent();
    } else {
    //Define the callback function when not logged in, and call it after app.js logs in successfully app.checkLoginReadyCallback = async () => {
        this.getUserInfo();
        this.getEvent();
      };
    }
  },

Advantages: Simple and crude

Disadvantages: Poor code structure; if multiple pages are startup pages, callback functions need to be defined for multiple pages (assuming the mini program onShare mode is used)

4.2.2 The elegant way

With the help of fly.js library, a locking mechanism for requests is implemented. Process: Login is initiated in app.js, and a request is also initiated on the page. In the request interceptor, determine whether the requested interface is on the whitelist (interface that does not require token verification) and whether the interface and token exist; if both are false, lock the current request into the request queue and execute the login process. After waiting for the login process to succeed, unlock the request queue and continue to initiate page-level request tasks. The following is the code in the request interceptor:

//Intercept processing fly.interceptors.request.use(async (request) => {
	// All requests without token and not in whitelist will be locked if (
		!getCache('token') &&
		!whiteList.some((item) => request.url.startsWith(item))
	) {
		fly.lock()
		//Unlock after successful login
		await doLogin()
		fly.unlock() //After unlocking, tasks in the request queue will continue to be initiated }

	if (getCache('token') && !fly.config.headers['Authorization']) {
		request.headers['Authorization'] = getCache('token')
	}
	request.headers['Content-Type'] = 'application/x-www-form-urlencoded'

	return request
})

Of course, custom login states may also expire. We can capture errors in the response interceptor for processing: when a 401 token expiration code is detected, all requests behind the request queue need to be locked to prevent multiple 401 custom login state expirations. Then initiate login, and unlock after successful login to trigger subsequent request queue executions, and re-execute the interface that was rejected by the server due to token expiration. Otherwise, the request will fail (since silent login is not perceived by users, the sudden expiration of authentication information will make users feel particularly strange, so it is necessary to re-execute this request operation instead of the user clicking again or initiating it through other actions):

// Response interception fly.interceptors.response.use(
	(response) => {
		//Only return the data field of the request result return response.data
	},
	async (err) => {
		if (err.status === 401) {
			//After 401, all subsequent requests are locked to prevent 401 again
			fly.lock()
			removeCache('token')
			//Unlock after successful login
			const isLoginSuccess = await doLogin()
			if (isLoginSuccess) {
				fly.unlock()
			}
                        // Newly execute the interface that was rejected by the server due to token expiration return fly.request(err.request)
		}
	}
)

Since the requests may be concurrent, in order to prevent the login from being executed multiple times, the doLogin function is slightly modified (although it is not written elegantly, but my ability is limited, so please enlighten me):

export async function doLogin() {
        //If you are logging in, do not execute if (isLogin) return false
	isLogin = true
        //Change the status to logged in, anyway, log in multiple times removeCache('token')
	const { code } = await wxp.login()
	const data = await login({ code })
	setCache('token', data.data.token)
	isLogin = false
	return true
}

4.3 Overall flow chart

5. Final Thoughts

Readers who pay attention to details will find that there is no maximum number of requests set in the API request (WeChat Mini Program supports up to five APIs being initiated simultaneously), which needs to be supplemented. Overall, the author feels that there is still room for improvement in the implementation methods. The author’s ability is limited, so he is also learning and discussing at the same time!

This is the end of this article about silent login and maintaining custom login status of WeChat Mini Program. For more relevant content about silent login of WeChat Mini Program, please search previous articles of 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • WeChat applet silent login implementation code

<<:  How to implement remote connection for Redis under Linux

>>:  Java imports data from excel into mysql

Recommend

Suggestions on creating business HTML emails

Through permission-based email marketing, not onl...

Solve the problem of invalid utf8 settings in mysql5.6

After the green version of mysql5.6 is decompress...

Detailed explanation of scheduled tasks and delayed tasks under Linux

at at + time at 17:23 at> touch /mnt/file{1..9...

Vue's vue.$set() method source code case detailed explanation

In the process of using Vue to develop projects, ...

Vue uses ECharts to implement line charts and pie charts

When developing a backend management project, it ...

JavaScript to implement drop-down list selection box

This article example shares the specific code of ...

How to understand the difference between computed and watch in Vue

Table of contents Overview computed watch monitor...

A brief analysis of adding listener events when value changes in html input

The effect to be achieved In many cases, we will ...

vue3 custom directive details

Table of contents 1. Registering custom instructi...

Detailed explanation of MySQL and Spring's autocommit

1 MySQL autocommit settings MySQL automatically c...

vue+element-ui implements the head navigation bar component

This article shares the specific code of vue+elem...

Research on the value of position attribute in CSS (summary)

The CSS position attribute specifies the element&...

How to mount a disk in Linux and set it to automatically mount on boot

Knowing that everyone's time is precious, I w...

Detailed installation tutorial of zabbix 4.04 (based on CentOS 7.6)

1. Preparation before installation: 1.1 Install J...