uni-app开发app保持登录状态
在 uni-app
中实现用户登录一次后在 token
过期前一直免登录的功能,可以通过以下几个关键步骤实现:本地持久化存储 Token、使用请求与响应拦截器自动处理 Token 刷新、以及在 App.vue
中结合 pages.json
设置登录状态跳转逻辑。
✅ 一、pages.json
配置说明
pages.json
是 uni-app
的全局配置文件,用于定义页面路径、窗口样式、启动页等。虽然它不直接支持登录状态判断,但可以配合 App.vue
的 onLaunch
生命周期实现登录状态的控制。
示例 pages.json
配置:
{"pages": [{"path": "pages/home/home","style": {"navigationBarTitleText": "主页"}},{"path": "pages/login/login","style": {"navigationBarTitleText": "登录"}}],"globalStyle": {"navigationBarTitleText": "uni-app","navigationBarBackgroundColor": "#ffffff","backgroundColor": "#ffffff"},"window": {"navigationBarTitleText": "uni-app"},"tabBar": {"list": [{"pagePath": "pages/home/home","text": "主页"},{"pagePath": "pages/user/user","text": "我的"}]}
}
⚠️ 注意:
pages.json
中 第一个页面 是默认启动页(即 App 启动时进入的第一个页面)。我们会在App.vue
中动态决定跳转哪一个页面。
✅ 二、App.vue 中实现登录状态判断
App.vue
的 onLaunch
生命周期是应用启动时的入口,适合在此判断用户是否已经登录(通过 Token 是否存在和是否过期),从而决定是否跳转到登录页或主页。
示例代码(App.vue):
<script>
export default {onLaunch() {// 检查本地是否存在有效的 tokenconst token = uni.getStorageSync('token');const expireTime = uni.getStorageSync('tokenExpireTime');if (token && Date.now() < expireTime) {// token 有效,跳转到主页uni.reLaunch({url: '/pages/home/home'});} else {// token 无效或不存在,跳转到登录页uni.reLaunch({url: '/pages/login/login'});}}
}
</script>
✅ 三、登录与 Token 存储逻辑
在登录成功后,需将 token
和 refreshToken
存入本地存储,并记录 token
的过期时间。
示例代码(login.vue):
<script>
export default {methods: {async handleLogin() {const res = await uni.request({url: 'https://api.example.com/login',method: 'POST',data: {username: this.username,password: this.password}});const { token, refreshToken, expiresIn } = res.data;// 存储 token 和 refresh tokenuni.setStorageSync('token', token);uni.setStorageSync('refreshToken', refreshToken);// 计算 token 过期时间(单位:毫秒)const expireTime = Date.now() + expiresIn * 1000;uni.setStorageSync('tokenExpireTime', expireTime);// 登录成功后跳转到主页uni.reLaunch({url: '/pages/home/home'});}}
}
</script>
✅ 四、请求与响应拦截器自动处理 Token
通过封装请求拦截器和响应拦截器,可以实现自动添加 token
到请求头、以及在 token
过期时自动刷新。
请求拦截器(添加 token)
uni.addInterceptor('request', {invoke(args) {const token = uni.getStorageSync('token');if (token) {args.header = {...args.header,Authorization: `Bearer ${token}`};}return args;}
});
响应拦截器(token 刷新)
uni.addInterceptor('request', {response: (res) => {if (res.statusCode === 401) {// token 过期,尝试刷新return refreshToken().then((newToken) => {uni.setStorageSync('token', newToken.token);uni.setStorageSync('tokenExpireTime', Date.now() + newToken.expiresIn * 1000);return uni.request(res.config); // 重新发送原请求}).catch(() => {uni.reLaunch({ url: '/pages/login/login' }); // 刷新失败则跳转登录页});}return res;}
});
refreshToken()
函数示例:
async function refreshToken() {const refreshToken = uni.getStorageSync('refreshToken');const res = await uni.request({url: 'https://api.example.com/refresh-token',method: 'POST',data: { refreshToken }});return res.data;
}
✅ 五、Token 即将过期时主动刷新
在每次请求前检查 token
是否即将过期,提前刷新以避免请求失败。
function isTokenExpired() {const now = Date.now();const expireTime = uni.getStorageSync('tokenExpireTime');return now >= expireTime;
}uni.addInterceptor('request', {invoke(args) {if (isTokenExpired()) {return refreshToken().then((newToken) => {uni.setStorageSync('token', newToken.token);uni.setStorageSync('tokenExpireTime', Date.now() + newToken.expiresIn * 1000);return uni.request(args); // 重新发送请求}).catch(() => {uni.reLaunch({ url: '/pages/login/login' });});}return args;}
});
✅ 六、安全建议(可选)
- 加密存储:使用
AES
或RSA
加密敏感数据(如token
)。 - Token 锁机制:防止多个请求同时触发刷新。
- 清理本地存储:用户登出时清除
token
和refreshToken
。 - 敏感信息不要明文存储。
✅ 七、总结
步骤 | 内容 |
---|---|
1. pages.json | 配置页面路径和启动页 |
2. App.vue | 使用 onLaunch 判断登录状态 |
3. 登录逻辑 | 登录成功后存储 token 和 refresh token |
4. 请求拦截器 | 自动添加 token 到请求头 |
5. 响应拦截器 | 自动刷新 token 并重试请求 |
6. 主动刷新 token | 在请求前检查 token 是否即将过期 |
通过以上完整流程,你可以实现用户在 uni-app
中登录一次后,在 token
过期前免登录的功能。