登录授权
登录授权
微信登录流程
小程序登录流程分为三步:
- 调用
wx.login()获取临时 code - 将 code 传给后端,后端调用
code2Session接口换取openid和session_key - 后端返回自定义登录态 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 有效性校验机制
Cao Note