Skip to content

登录授权 ​

登录授权 ​

微信登录流程 ​

小程序登录流程分为三步:

  1. 调用 wx.login() 获取临时 code
  2. 将 code 传给后端,后端调用 code2Session 接口换取 openid 和 session_key
  3. 后端返回自定义登录态 token,前端存储并用后续请求
js
App({
  onLaunch() {
    this.login()
  },
  login() {
    wx.login({
      success: (res) => {
        if (res.code) {
          // 将 code 发送到后端
          wx.request({
            url: 'https://api.example.com/login',
            method: 'POST',
            data: { code: res.code },
            success: (response) => {
              // 存储 token
              wx.setStorageSync('token', response.data.token)
            }
          })
        } else {
          console.error('登录失败:', res.errMsg)
        }
      }
    })
  }
})
App({
  onLaunch() {
    this.login()
  },
  login() {
    wx.login({
      success: (res) => {
        if (res.code) {
          // 将 code 发送到后端
          wx.request({
            url: 'https://api.example.com/login',
            method: 'POST',
            data: { code: res.code },
            success: (response) => {
              // 存储 token
              wx.setStorageSync('token', response.data.token)
            }
          })
        } else {
          console.error('登录失败:', res.errMsg)
        }
      }
    })
  }
})

登录态检查 ​

每次启动时检查 token 是否有效,无效则重新登录。

js
const TOKEN_EXPIRY = 7200 // token 有效期(秒)

function checkLogin() {
  const token = wx.getStorageSync('token')
  const loginTime = wx.getStorageSync('loginTime')

  if (!token || !loginTime) return false

  const now = Date.now()
  const elapsed = (now - loginTime) / 1000

  return elapsed < TOKEN_EXPIRY
}
const TOKEN_EXPIRY = 7200 // token 有效期(秒)

function checkLogin() {
  const token = wx.getStorageSync('token')
  const loginTime = wx.getStorageSync('loginTime')

  if (!token || !loginTime) return false

  const now = Date.now()
  const elapsed = (now - loginTime) / 1000

  return elapsed < TOKEN_EXPIRY
}

用户信息授权 ​

方式一:使用 button 组件引导授权(推荐) ​

从微信基础库 2.21.0 起,wx.getUserProfile 已被收回,推荐使用 <button open-type="getUserInfo"> 方式获取用户信息。

html
<button open-type="getUserInfo" bindgetuserinfo="onGetUserInfo">
  获取头像昵称
</button>
<button open-type="getUserInfo" bindgetuserinfo="onGetUserInfo">
  获取头像昵称
</button>

方式二:头像昵称填写(基础库 2.21.2+) ​

利用原生 form 组件实现用户填写头像和昵称:

html
<form>
  <button open-type="chooseAvatar" bindchooseavatar="onChooseAvatar">
    <image src="{{avatarUrl}}" />
  </button>
  <input type="nickname" placeholder="请输入昵称" />
</form>
<form>
  <button open-type="chooseAvatar" bindchooseavatar="onChooseAvatar">
    <image src="{{avatarUrl}}" />
  </button>
  <input type="nickname" placeholder="请输入昵称" />
</form>
js
Page({
  data: {
    avatarUrl: ''
  },
  onChooseAvatar(e) {
    this.setData({
      avatarUrl: e.detail.avatarUrl
    })
  }
})
Page({
  data: {
    avatarUrl: ''
  },
  onChooseAvatar(e) {
    this.setData({
      avatarUrl: e.detail.avatarUrl
    })
  }
})

手机号获取 ​

利用 <button open-type="getPhoneNumber"> 获取用户手机号。

html
<button open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">
  获取手机号
</button>
<button open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">
  获取手机号
</button>
js
Page({
  onGetPhoneNumber(e) {
    if (e.detail.code) {
      // 将 code 发送到后端,后端调用接口换取手机号
      wx.request({
        url: 'https://api.example.com/phone',
        method: 'POST',
        data: { code: e.detail.code }
      })
    } else {
      // 用户拒绝授权
      wx.showToast({
        title: '需要授权才能继续',
        icon: 'none'
      })
    }
  }
})
Page({
  onGetPhoneNumber(e) {
    if (e.detail.code) {
      // 将 code 发送到后端,后端调用接口换取手机号
      wx.request({
        url: 'https://api.example.com/phone',
        method: 'POST',
        data: { code: e.detail.code }
      })
    } else {
      // 用户拒绝授权
      wx.showToast({
        title: '需要授权才能继续',
        icon: 'none'
      })
    }
  }
})

授权状态管理 ​

检查授权状态 ​

js
wx.getSetting({
  success: (res) => {
    if (res.authSetting['scope.userInfo']) {
      // 已授权
    } else {
      // 未授权,引导授权
    }
  }
})
wx.getSetting({
  success: (res) => {
    if (res.authSetting['scope.userInfo']) {
      // 已授权
    } else {
      // 未授权,引导授权
    }
  }
})

跳转授权设置页 ​

当用户拒绝授权后,引导用户前往设置页手动开启:

js
wx.showModal({
  title: '提示',
  content: '需要获取您的用户信息,请前往设置',
  success: (res) => {
    if (res.confirm) {
      wx.openSetting()
    }
  }
})
wx.showModal({
  title: '提示',
  content: '需要获取您的用户信息,请前往设置',
  success: (res) => {
    if (res.confirm) {
      wx.openSetting()
    }
  }
})

完整登录流程示例 ​

js
// utils/auth.js
const TOKEN_KEY = 'token'

export function login() {
  return new Promise((resolve, reject) => {
    // 1. 检查已有 token
    const token = wx.getStorageSync(TOKEN_KEY)
    if (token) {
      return resolve(token)
    }

    // 2. 获取 code
    wx.login({
      success: (res) => {
        if (!res.code) {
          return reject(new Error('登录失败'))
        }

        // 3. 后端换取登录态
        wx.request({
          url: 'https://api.example.com/login',
          method: 'POST',
          data: { code: res.code },
          success: (response) => {
            const { token } = response.data
            wx.setStorageSync(TOKEN_KEY, token)
            resolve(token)
          },
          fail: reject
        })
      },
      fail: reject
    })
  })
}
// utils/auth.js
const TOKEN_KEY = 'token'

export function login() {
  return new Promise((resolve, reject) => {
    // 1. 检查已有 token
    const token = wx.getStorageSync(TOKEN_KEY)
    if (token) {
      return resolve(token)
    }

    // 2. 获取 code
    wx.login({
      success: (res) => {
        if (!res.code) {
          return reject(new Error('登录失败'))
        }

        // 3. 后端换取登录态
        wx.request({
          url: 'https://api.example.com/login',
          method: 'POST',
          data: { code: res.code },
          success: (response) => {
            const { token } = response.data
            wx.setStorageSync(TOKEN_KEY, token)
            resolve(token)
          },
          fail: reject
        })
      },
      fail: reject
    })
  })
}

注意事项 ​

  • wx.login() 每次调用都会生成新的 code,一个 code 只能使用一次
  • session_key 不应传到前端或通过前端转发,应直接在后端使用
  • 不要将 openid 和 session_key 泄露给第三方
  • 建议为每个请求添加 token 有效性校验机制