记得我刚接触小程序开发时,最让我困惑的就是登录流程。明明调用了wx.login(),拿到了code,用户为什么还要点击授权?session_key到底是什么时候生成的?这些问题困扰了我好一阵子。
经过多个项目的实践,我终于摸清了小程序登录的完整流程。今天就跟大家分享一下这个"从点击到识别"的完整旅程。
第一步:静默登录 - 无感知的身份准备
小程序登录的第一步往往发生在用户毫无感知的情况下:
javascript
// 应用启动时执行静默登录
onLaunch() {
this.silentLogin();
},
async silentLogin() {
try {
// 获取临时code
const loginRes = await wx.login();
if (loginRes.code) {
// 将code发送到后端换取session_key和openid
const authRes = await wx.request({
url: 'https://api.example.com/auth/login',
method: 'POST',
data: {
code: loginRes.code
}
});
if (authRes.data.success) {
// 保存登录态到全局
getApp().globalData.sessionKey = authRes.data.sessionKey;
getApp().globalData.openId = authRes.data.openId;
getApp().globalData.isLoggedIn = true;
console.log('静默登录成功,用户身份已准备就绪');
}
}
} catch (error) {
console.error('静默登录失败:', error);
}
}
这里有个很重要的点:此时的登录只是确认了微信用户的身份,我们拿到了openid,但还没有获取用户的基本信息。
第二步:用户信息授权 - 完善用户画像
当我们需要用户昵称、头像等信息时,就要触发授权流程:
javascript
// 用户信息授权
getUserProfile() {
wx.getUserProfile({
desc: '用于完善用户资料',
success: (res) => {
const userInfo = res.userInfo;
this.setData({
nickName: userInfo.nickName,
avatarUrl: userInfo.avatarUrl
});
// 将用户信息同步到后端
this.syncUserInfo(userInfo);
},
fail: (err) => {
console.log('用户拒绝授权:', err);
this.showAuthGuide();
}
});
},
async syncUserInfo(userInfo) {
// 结合之前获取的openid,完善用户资料
await wx.request({
url: 'https://api.example.com/user/update',
method: 'POST',
data: {
openId: getApp().globalData.openId,
nickName: userInfo.nickName,
avatarUrl: userInfo.avatarUrl,
gender: userInfo.gender
}
});
}
第三步:登录状态维护 - 保持用户会话
登录状态的管理是个技术活,我通常这样处理:
javascript
// 检查登录状态
checkLoginStatus() {
const app = getApp();
if (!app.globalData.isLoggedIn) {
// 未登录,重新执行静默登录
this.silentLogin();
return false;
}
// 验证session_key是否过期
this.checkSessionValidity();
return true;
},
async checkSessionValidity() {
try {
await wx.checkSession();
console.log('session_key 未过期');
} catch (error) {
console.log('session_key 已过期,重新登录');
// session_key过期,重新登录
await this.silentLogin();
}
}
第四步:完整的登录流程封装
在实际项目中,我会把整个登录流程封装成一个可重用的模块:
javascript
class AuthManager {
constructor() {
this.isLogging = false;
}
// 确保登录的通用方法
async ensureLogin() {
if (this.isLogging) {
return await this.waitForLogin();
}
const app = getApp();
// 如果已经登录,检查session有效性
if (app.globalData.isLoggedIn) {
const isValid = await this.checkSessionValidity();
if (isValid) {
return true;
}
}
// 执行登录流程
return await this.performLogin();
}
async performLogin() {
this.isLogging = true;
try {
// 执行静默登录
await this.silentLogin();
// 检查是否需要用户信息授权
const needUserInfo = await this.checkIfNeedUserInfo();
if (needUserInfo) {
await this.requestUserInfo();
}
this.isLogging = false;
return true;
} catch (error) {
this.isLogging = false;
console.error('登录流程失败:', error);
return false;
}
}
async checkIfNeedUserInfo() {
// 检查本地存储,判断是否已经获取过用户信息
const userInfo = wx.getStorageSync('userInfo');
return !userInfo;
}
}
那些年踩过的坑
- session_key过期处理 :第一次上线时,我没处理session_key过期的情况,导致部分用户使用一段时间后无法正常请求。后来加了
wx.checkSession()才解决。 - 重复登录问题 :在多个页面同时调用登录接口时,会造成重复登录。后来我加入了登录状态锁
isLogging来解决。 - 用户拒绝授权的处理:不能因为用户拒绝授权就阻断流程,要提供降级方案:
javascript
showAuthGuide() {
wx.showModal({
title: '提示',
content: '授权后可以获得更好的体验,您可以在设置中重新授权。',
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
wx.openSetting();
}
}
});
}
最佳实践总结
- 分层登录:先静默登录确认身份,再按需获取用户信息
- 状态管理:妥善管理session_key的生命周期
- 错误处理:对用户拒绝授权、网络异常等情况都要有降级方案
- 用户体验:登录过程要流畅,避免阻塞用户操作
小程序的登录流程就像是一场精心编排的舞蹈,每个步骤都要恰到好处。掌握了这个流程,你就能为用户提供既安全又流畅的登录体验。
希望这篇文章能帮你理清小程序登录的脉络。如果你在实践过程中遇到其他问题,欢迎在评论区交流讨论!
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!