在Uniapp中结合uni-simple-router和Vuex实现一个优雅且安全的登录流程。
1. 使用uni-simple-router进行路由管理
配置路由守卫,检查用户登录状态:
import store from './store';
export const routes = [
{
path: '/index',
component: () => import('@/pages/Index.vue'),
beforeEnter: (to, from, next) => {
if (store.state.user.isLoggedIn) {
next();
} else {
store.commit('SET_REDIRECT_URL', to.fullPath);
next('/login');
}
}
},
{
path: '/login',
component: () => import('@/pages/Login.vue')
}
];
2. 在登录页面实现登录逻辑
// 登录页面 methods
methods: {
login() {
wx.login({
success: res => {
if (res.code) {
uni.request({
url: 'https://yourserver.com/api/login',
method: 'POST',
data: { code: res.code },
success: res => {
const token = res.data.token;
this.$store.dispatch('loginSuccess', token).then(() => {
const redirectUrl = this.$store.state.user.redirectUrl;
if (redirectUrl) {
uni.redirectTo({ url: redirectUrl });
} else {
uni.switchTab({ url: '/pages/index/index' });
}
});
},
fail: () => {
console.log('获取token失败');
}
});
} else {
console.log('登录失败:' + res.errMsg);
}
}
});
}
}
3. 使用Vuex管理全局状态
定义Vuex store:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
user: {
isLoggedIn: false,
token: '',
redirectUrl: ''
}
},
mutations: {
SET_TOKEN(state, token) {
state.user.token = token;
uni.setStorageSync('token', token);
},
SET_REDIRECT_URL(state, url) {
state.user.redirectUrl = url;
},
LOGOUT(state) {
state.user.isLoggedIn = false;
state.user.token = '';
state.user.redirectUrl = '';
uni.removeStorageSync('token');
}
},
actions: {
loginSuccess({ commit }, token) {
return new Promise((resolve) => {
commit('SET_TOKEN', token);
commit('SET_REDIRECT_URL', '');
commit('SET_IS_LOGGED_IN', true);
resolve();
});
},
logout({ commit }) {
commit('LOGOUT');
}
}
});
4. 在请求拦截器中添加token
uni.addInterceptor({
request: (options) => {
const token = this.$store.state.user.token;
if (token) {
options.header = options.header || {};
options.header.Authorization = 'Bearer ' + token;
}
return options;
},
response: (options) => {
if (options.statusCode === 401) {
this.$store.dispatch('logout');
uni.reLaunch({ url: '/pages/login/login' });
}
return options;
}
});
5. 处理token刷新机制(可选)
// 在请求拦截器中处理token刷新
uni.addInterceptor({
request: (options) => {
const token = this.$store.state.user.token;
if (token) {
options.header = options.header || {};
options.header.Authorization = 'Bearer ' + token;
}
return options;
},
response: (options) => {
if (options.statusCode === 401) {
// 使用refresh token刷新access token
this.$store.dispatch('refreshToken').then(() => {
// 重试请求
return uni.request(options);
}).catch(() => {
this.$store.dispatch('logout');
uni.reLaunch({ url: '/pages/login/login' });
});
}
return options;
}
});
6. 完善Vuex中的refreshToken action
actions: {
refreshToken({ state, commit }) {
return new Promise((resolve, reject) => {
uni.request({
url: 'https://yourserver.com/api/refresh',
method: 'POST',
data: { refreshToken: state.user.refreshToken },
success: res => {
commit('SET_TOKEN', res.data.token);
resolve();
},
fail: () => {
reject();
}
});
});
}
}