导言
在用C#搞完个后端后想用若依的前端做对接,不过很久没搞过若依了,想趁这个二次开发的过程记录熟悉一下登录的过程
过程
验证,在permission.js的路由守卫,这里在用户发起api请求时会验证用户的请求是否有token,对应访问的权限,并进行相应的拦截和跳转
router.beforeEach((to, from, next) => {
NProgress.start()
//如果有token
if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
/* has token*/
//如果在登录
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
//不在登录的话根据用户角色动态生成路由表
if (store.getters.roles.length === 0) {
isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
isRelogin.show = false
store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else {
next()
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
console.log("//如果在登录");
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
1.获取验证码图片,展示
从登录页面开始先调后端拿验证码图片和从cookie拿到之前保存的用户登录信息
然后在api定义请求后端接口的方法格式与所要传递的参数,这里不需要传token
//在api/login
// 获取验证码
export function getCodeImg() {
return request({
url: '/api/Auth/Code',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}
接到后端返回验证码(Base64 编码)后,前端对应显示在页面上
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
...
getCode() {
//调用拿验证码
getCodeImg().then(res => {
console.log(res,",验证码");
this.captchaEnabled = res.statusCode === 200 ? true : res.captchaCode;
if (this.captchaEnabled) {
console.log("进来了",res.data.captchaGUID)
this.codeUrl = res.data.captchaCode;
this.loginForm.uuid = res.data.captchaGUID;
}
});
},
验证码大概长这样
{
"captchaImage": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}
2.登录提交,存token
用户点击提交表单(登录)后前端将所需的东西传回后端验证,具体是先调store中的登录方法,这样好存token
//login.vue
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true;
if (this.loginForm.rememberMe) {
Cookies.set("username", this.loginForm.username, { expires: 30 });
Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
} else {
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove('rememberMe');
}
//调后端登录接口 先是从持久化那调,
//然后在那边调完就存token 再把登录成功的信息 传过来
this.$store.dispatch("Login", this.loginForm).then(() => {
console.log("登录处理成功!");
this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
}).catch(() => {
this.loading = false;
if (this.captchaEnabled) {
this.getCode();
}
});
}
});
}
3.用户信息持久化
存完之后在handleLogin最后跳转路由之前会在路由守卫那进到if (store.getters.roles.length === 0),即已经有token和不在登录界面。这时需要用户角色来动态生成路由与存用户的信息,所以还要请求后端拿到用户的详细信息
同理也是先调store中的相应方法,在通过这个来调请求后端的方法
//先调这个 在...src\store\modules\user.js
// 获取用户信息
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
//在这里调请求后端的方法
getInfo().then(res => {
//成功后做持久化
console.log("用户信息:",res);
const user = res.data
const avatar = (user.avatarUrl == "" || user.avatarUrl == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatarUrl;
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.roles)
commit('SET_PERMISSIONS', res.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
commit('SET_ID', user.userId)
commit('SET_NAME', user.userName)
commit('SET_AVATAR', avatar)
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 获取用户详细信息
export function getInfo() {
return request({
headers: {
isToken: true
},
url: '/api/Auth/GetUserInfo',
method: 'get'
})
}
4.生成动态路由菜单
请求后端获得菜单树,在前端根据用户角色(管理员和普通用户)将其转换为菜单
// 生成路由 在src\store\modules\permission.js
GenerateRoutes({ commit }) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
router.addRoutes(asyncRoutes);
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', sidebarRoutes)
resolve(rewriteRoutes)
})
})
}
之后路由守卫放行,进到主页..
结语
登录过程不是很复杂,主要就是路由守卫的一系列验证筛选,把不合规范的请求和路由跳转都筛掉了。
正常登录流程大概是验证码图片获取,登录提交,token,用户信息的持久化和菜单生成...