uniapp中保存非第三方登录信息,可通过本地存储API实现,如uni.setStorageSync存储用户token、账号等敏感数据,需注意H5端使用localStorage,小程序用uniStorage,App端兼容本地存储,敏感信息建议加密处理(如AES),读取时通过uni.getStorageSync获取,结合全局变量管理登录状态,清除则用uni.removeStorageSync,此方案轻量跨平台,无需第三方SDK,适用于常规账号密码登录场景,实现登录状态持久化管理。
Uniapp本地保存登录信息实现:打造独立自主的用户认证系统
在移动应用开发领域,用户登录功能作为应用安全与用户体验的核心环节,其重要性不言而喻,许多开发者倾向于快速接入微信、QQ等第三方登录服务,但对于注重品牌独立性、追求数据自主掌控的应用场景而言,本地保存登录信息(非第三方登录)无疑是更优的选择,本文将深入探讨如何在Uniapp框架中,利用本地存储技术实现登录信息的持久化保存,让用户获得无缝的登录体验,同时确保数据安全与应用的独立性。
核心原理:本地存储与状态管理的完美结合
本地保存登录信息的核心逻辑可概括为:用户成功登录后,将身份凭证(如Token、用户ID等关键信息)安全地存储在设备本地,当应用下次启动时自动读取并校验这些凭证的有效性,若凭证未过期则自动恢复用户的登录状态。
Uniapp框架提供了丰富的本地存储API(如uni.setStorage、uni.getStorage等),配合Vuex或Pinia等状态管理工具,可以轻松构建一套完整的本地登录持久化解决方案,这种方案不仅减少了第三方依赖,还能更好地保护用户隐私数据。
详细实现步骤
设计登录接口与返回数据结构
后端系统需要提供一套完善的登录接口,返回包含用户身份信息的结构化数据,典型的响应数据应包含以下关键字段:
token:用于后续API调用的加密访问令牌(建议设置合理的有效期,如7天)refreshToken:用于刷新访问令牌的凭证(可选但推荐)userId:系统中用户的唯一标识符userInfo:用户基础信息(如昵称、头像、手机号等,根据业务需求选择性返回)
标准响应格式示例:
{
"code": 200,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwicmVmcmVzaCI6IjEwODZiIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"userId": "10086",
"userInfo": {
"nickname": "张三",
"avatar": "/static/avatar.png",
"phone": "138****1234",
"email": "zhangsan@example.com"
}
}
}
登录成功后保存信息到本地
当用户在登录页面输入账号密码并通过验证后,需要将关键信息安全地存储到本地,推荐使用uni.setStorageSync(同步API)简化逻辑,也可使用异步APIuni.setStorage避免阻塞主线程。
登录页面核心代码示例:
// 登录方法
async handleLogin() {
try {
// 显示加载提示
uni.showLoading({ title: '登录中...', mask: true });
// 调用后端登录接口
const res = await uni.request({
url: 'https://your-api.com/login',
method: 'POST',
data: {
username: this.username,
password: this.password,
deviceInfo: this.getDeviceInfo() // 可选:设备信息
}
});
// 处理响应结果
if (res.data.code === 200) {
const { token, refreshToken, userId, userInfo } = res.data.data;
// 构建登录信息对象
const loginInfo = {
token,
refreshToken,
userId,
userInfo,
expireTime: Date.now() + 7 * 24 * 60 * 60 * 1000, // 7天后过期
loginTime: Date.now() // 记录登录时间
};
// 保存到本地存储(建议加密处理)
this.saveLoginInfo(loginInfo);
// 更新全局状态
this.updateGlobalState(loginInfo);
// 记录用户行为日志(可选)
this.logUserAction('login', { userId });
// 跳转到首页
uni.switchTab({
url: '/pages/index/index',
success: () => {
uni.hideLoading();
uni.showToast({ title: '登录成功', icon: 'success' });
}
});
} else {
// 登录失败处理
uni.hideLoading();
uni.showToast({
title: res.data.message || '登录失败',
icon: 'none',
duration: 2000
});
}
} catch (error) {
// 异常处理
uni.hideLoading();
console.error('登录异常:', error);
uni.showToast({
title: '网络异常,请稍后重试',
icon: 'none'
});
}
},
// 保存登录信息到本地
saveLoginInfo(info) {
// 可以在这里添加加密逻辑
uni.setStorageSync('loginInfo', info);
},
// 更新全局状态
updateGlobalState(info) {
// 更新Vuex/Pinia状态
this.$store.commit('setLoginInfo', info);
// 也可以使用全局变量
getApp().globalData.isLoggedIn = true;
getApp().globalData.userInfo = info.userInfo;
},
// 获取设备信息(可选)
getDeviceInfo() {
return {
platform: uni.getSystemInfoSync().platform,
version: uni.getSystemInfoSync().version,
system: uni.getSystemInfoSync().system
};
},
// 记录用户行为(可选)
logUserAction(action, data) {
// 实现用户行为日志记录
}
应用启动时自动校验登录状态
在App.vue的onLaunch生命周期中,需要实现登录状态的自动校验逻辑,确保用户能够无缝恢复之前的登录状态。
App.vue核心代码示例:
export default {
onLaunch() {
console.log('App Launch');
// 获取本地存储的登录信息
const loginInfo = this.getLoginInfo();
if (loginInfo) {
const { token, expireTime } = loginInfo;
// 校验token是否过期
if (Date.now() < expireTime) {
// Token有效,恢复登录状态
this.restoreLoginState(loginInfo);
// 可选:静默刷新token
this.silentRefreshToken(loginInfo);
} else {
// Token已过期,清除本地信息
this.clearLoginInfo();
console.log('登录已过期,请重新登录');
}
}
// 初始化应用配置
this.initAppConfig();
},
// 获取登录信息(可添加解密逻辑)
getLoginInfo() {
try {
return uni.getStorageSync('loginInfo');
} catch (e) {
console.error('读取登录信息失败:', e);
return null;
}
},
// 恢复登录状态
restoreLoginState(loginInfo) {
// 更新全局状态
this.$store.commit('setLoginInfo', loginInfo);
// 更新全局变量
this.globalData.isLoggedIn = true;
this.globalData.userInfo = loginInfo.userInfo;
this.globalData.token = loginInfo.token;
console.log('已恢复登录状态');
},
// 静默刷新token(可选)
async silentRefreshToken(loginInfo) {
try {
// 检查token是否即将过期(比如剩余2小时)
const remainingTime = loginInfo.expireTime - Date.now();
if (