微信小程序登录流程(详细+图解)

9,566 阅读4分钟

💂 个人网站:【紫陌】【笔记分享网】
💅 想寻找共同学习交流、共同成长的伙伴,请点击【前端学习交流群】

微信小程序的登录和web端的登录有一点是不同的,小程序需要和微信的服务通信验证。

1.小程序登录流程官网图

官网图地址

2.认识openid,unionid 和code

  1. openid

openid是用来唯一标识用户的一个字符串。在微信小程序中,每个用户的openid都是唯一的。通过openid,小程序可以获取用户的基本信息,如头像、昵称等。

注意: 同一个用户在不同的小程序中拥有不同的openid。因此,在开发小程序时,不能使用openid来进行用户的唯一性判断。

  1. unionid

unionid是在用户绑定同一微信开放平台账号下的多个应用时,用来唯一标识用户的一个字符串。如果用户在多个小程序中使用同一个微信号进行登录授权,那么这些小程序中的unionid都是相同的。

注意: 用户的unionid只有在用户将多个应用绑定到同一个微信开放平台账号下时才会生成。因此,如果用户没有绑定多个应用,那么小程序将无法获取用户的unionid。

  1. code

code是用户登录凭证,由微信服务器颁发给小程序。在用户授权登录后,小程序可以通过调用微信登录接口获取用户的code。然后,通过code向微信服务器请求用户的openid和session_key等信息。

注意: 每个code只能使用一次,且有效期为5分钟。因此,在使用code进行登录时,需要及时将其转换成用户的openid和session_key等信息,以免出现code过期的情况

openid、unionid和code是微信小程序登录授权中非常重要的三个参数,了解这些参数的作用和用法,有助于开发者更好地设计和开发小程序登录授权功能。

3.文字版登录流程(面试会问这个,回答这个即可)

  1. 通过wx.login()获取code。
  2. 将这个code发送给后端,后端会返回一个token,这个token将作为你身份的唯一标识。
  3. 将token通过wx.setStorageSync()保存在本地存储。
  4. 用户下次进入⻚面时,会先通过wx.getStorageSync() 方法判断token是否有值,如果有值,则可以请求其它数据,如果没有值,则进行登录操作。

4.图形流程(前端流程和后端流程)

前端步骤:

后端步骤:

5. 代码实现登录流程

  1. 简单的实现登录流程。

  1. 再进一步完善:把登录封装成一个函数,然后判读本地是否有token有就不用执行登录函数,否则执行登录函数。
  onLoad() {
    //获取token, 判断token是否有值
    const token = wx.getStorageSync('token') || ''
    //如果有值
   if(token) {
    console.log('请求其他数据');
   }else{
     this.handlerLogin()
   }
  },
  //登录的回调函数
  handlerLogin(){
    wx.login({
      success: res => {
        //获取code
        const code = res.code
        console.log(res);
        //将code发给后端请求token
        wx.request({
          url: 'http://xxxxxxx/login',
          data:{ code },
          method:'post',
          success:(res) =>{
            const token = res.data.token
            //将token保存本地
            wx.setStorageSync('token', token)
            console.log(res);
          }
        })
      }
    })
  },
  1. 在一次优化代码:

看看刚刚写的代码的问题

所以要对代码优化,把上面的代码进行拆分。

  1. 首先在项目的service文件夹下声明一个login.js用来获取code。使用promise返回成功的code

export const getCode = () => {
  new Promise((resolve, reject) => {
    wx.login({
      success: res => {
        //获取code
        resolve(res.code)
      }
    })
  })
}
  1. 二次封装一个Promise版的request请求方法,在service下建立一个index.js(后面出一篇封装请求的文章)

// 封装成类 
class Request {
  constructor(baseURL) {
    this.baseURL = baseURL
  }
  request(options) {
    const { url } = options
    return new Promise((resolve, reject) => {
      wx.request({
        ...options,
        url: this.baseURL + url,
        success: (res) => {
          resolve(res.data)
        },
        fail: (err) => {
          console.log("err:", err);
        }
      })
    })
  }
  get(options) {
    return this.request({ ...options, method: "get" })
  }
  post(options) {
    return this.request({ ...options, method: "post" })
  }
}
export const loginRequest = new Request("http://xxxxxxx")
  1. 使用自己封装的请求方法

import { loginRequest } from "./service/index";
import { getCode } from "./service/login";

// app.js
App({
  onLaunch() {
    const token = wx.getStorageSync('token') || ''
    // 登录
   if(token) {
    console.log('请求其他数据');
   }else{
     this.handlerLogin()
   }
  },
  //登录的回调函数
  async handlerLogin(){
    //获取code
    const code = await getCode()

    //将code发给后端请求token
    const res = await loginRequest.post({
      url:"/login",
      data:{code}
    })
    
    //保存token
    wx.setStorageSync('token', res.token)
  },
}
  1. 对比优化前后

  1. 添加一个判断token是否过期,本地的token可能有可能没有,有的token的话,token还有可能是否过期,token是有时效的。后端给我们一个借口验证token是否过期的。

最后:发一个总体代码:结合实际更改代码

import { loginRequest } from "./service/index"
import { getCode } from "./service/login"

// app.js
App({
  async onLaunch() {
    //获取本地token
    const token = wx.getStorageSync('token') || ''

    //检查token是否过期
    const res = await loginRequest.post({
      url: '/auth',
      header: {
        token
      }
    })
    console.log(res);

    // 登录
    if (token && res.message === "已登录") {
      console.log('请求其他数据');
    } else {
      this.handlerLogin()
    }
  },
  //登录的回调函数
  async handlerLogin() {
    //获取code
    const code = await getCode()

    //将code发给后端请求token
    const res = await loginRequest.post({
      url: "/login",
      data: { code }
    })

    //保存token
    wx.setStorageSync('token', res.token)
  },
})



//service/index.js代码
// 封装成类 
class Request {
  constructor(baseURL) {
    this.baseURL = baseURL
  }
  request(options) {
    const { url } = options
    return new Promise((resolve, reject) => {
      wx.request({
        ...options,
        url: this.baseURL + url,
        success: (res) => {
          resolve(res.data)
        },
        fail: (err) => {
          console.log("err:", err);
        }
      })
    })
  }
  get(options) {
    return this.request({ ...options, method: "get" })
  }
  post(options) {
    return this.request({ ...options, method: "post" })
  }
}
export const loginRequest = new Request("http://xxxxx")



//service/login.js
export const getCode = () => {
  new Promise((resolve, reject) => {
    wx.login({
      success: res => {
        //获取code
        resolve(res.code)
      }
    })
  })
}

最后哪里需要改进的麻烦大家指点江山。对你有帮助可以点点赞~。需要技术交流的也可加入技术群聊!