引言
几年7-8月份的时候我连续发表了几篇spring-boot
整合vue-element-admin
项目实现自定义权限控制的实战文章,后面也受到了不少读者的点赞。后面自己也没注意去维护了,但是最近在CSDN上有一个粉丝还是一名高校教师突然给我留言说按照我的文章思路搭建了项目,也实现了自定义菜单和角色授权等功能。但是发现了一个很严重的bug,那就是退出登录无效,且退出登录后系统不会调到登录界面,点击其他页面也是一片空白。
图 1 读者反馈的项目退出登录失效bug
据这位读者反馈,这个问题困扰了他一周了都没法解决,于是只好留言向我求助。本着帮粉丝解决问题的同时也是在提升自己的想法,于是我重新启动项目开启了这个自己放在一边很久项目的调试之路,同时也参考了之前的luban-mall
前后端分离项目,花了一个晚上终于把问题解决了,这一刻自己又找到了一丢丢的成就感!好久没更新公众号,顺便也把解决前后端分离且使用spring-security作为安全框架的场景下自定义退出登录的具体实现。
找到前端退出登录按钮的实现逻辑并定位问题
首先我们得找到实现退出登录按钮代码的地方,它在vue-element-admin
项目的src/layout/components/Navbar.vue
文件中logout
方法中。
「修改前的逻辑」
async logout() {
await this.$store.dispatch('user/logout')
this.$router.push('/login')
}
然后我们根据this.$store.dispatch('user/logout')
这段代码找到src/store/user.js
文件里actions
里的 logout
行为方法,发现原来的退出登录逻辑里面是虽然调用后台退出登录接口,但是并没有走后台退出登录的逻辑。
logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_NAME', '')
commit('SET_CURRENT_ROLE', null)
window.sessionStorage.removeItem('userInfo')
window.sessionStorage.removeItem('routeIds')
window.sessionStorage.removeItem('roles')
window.sessionStorage.removeItem('currentRole')
removeToken()
resetRouter()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
}).catch(error => {
reject(error)
})
})
}
每次在前端调试退出登录功能的时候,浏览器控制台中会报出一个如下所示的跨域失败的问题,导致交互压根到不了后台退出登录的接口
图 2 前端退出登录时浏览器控制台报跨域失败
明明我在后端的spring-security配置类中是配置了跨域的,在这个前后端分离的项目中登录功能也是走的跨域完全没问题,为什么退出登录时还会报这样的跨域问题呢?这里就涉及到后台修改spring-security适配器类中的代码了
后台spring-security适配器类中禁用框架的退出登录
好在参考了我目前就职的公司里面spring-security配置类中的源码,发现需要在spring-security配置类中的禁用框架自带的退出登录。
WebSecurityConfig.java
这个spring-security的适配器类位于我的blogserver
项目的src/main/java/org/sang/config
目录下
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置跨域
http.cors().configurationSource(corsConfigurationSource());
// 禁用spring security框架的退出登录,使用自定义退出登录
http.logout().disable();
// 其他代码省略
}
为了验证登录和退出登录的逻辑,我么分别在登录和退出登录的方法中都打上日志
UserService.java
这个类位于我的blogserver
项目的src/main/java/org/sang/service
目录下
图 3 后台项目中用户登录业务失效逻辑代码
UserController.java
这个类位于我的blogserver
项目的src/main/java/org/sang/controller
目录下
图 4 后台项目自定义用户退出登录业务逻辑代码
退出登录方法中调用Util.clearContext()
方法会在应用上下文中清空当前用户的认证信息
修改前端退出登录逻辑
后端禁用spring-security框架的退出登录后我们开始来修改前端退出登录逻辑
首先我们在前端vue-element-admin
项目中的src/api/user.js
文件中暴露一个退出登录的接口
export function logout() {
return request({
url: '/user/logout',
method: 'post'
})
}
然后在src/store/user.js
文件中导入退出登录的接口并在退出登录行为方法中调用该接口
import { login, logout } from '@/api/user'
// 中间部分代码省略,需要查看完整代码的读者可前往代码仓库查看
const actions = {
// login({ commit }, userInfo) 省略
logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {
logout().then(res => {
if (res.status === 200) {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_NAME', '')
commit('SET_CURRENT_ROLE', null)
window.sessionStorage.removeItem('userInfo')
window.sessionStorage.removeItem('routeIds')
window.sessionStorage.removeItem('roles')
window.sessionStorage.removeItem('currentRole')
removeToken()
resetRouter()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
Message.info('退出登录成功')
// 下面这个resolve方法必须调用,否则如法到达Navbar组件中退出登录回调方法进行路由跳转到登录页面
resolve()
} else {
reject('退出登录失败')
}
})
})
}
}
在后端退出登录成功后前端的cookie和session中我们也需要清空用户的缓存信息。
最后我们还要在Navbar.vue
文件中的调用this.$store.dispatch('user/logout')
方法的成功回调方法中刷新当前文档,并让当前路由重新进入登录界面。代码实现逻辑如下:
logout() {
this.$store.dispatch('user/logout').then(res => {
console.log(res)
// 刷新当前文档
location.reload()
this.$router.push({ path: '/login' })
})
}
以上逻辑与vue-element-vue
项目中原作者的退出登录逻辑稍作了修改,这里我把异步方法改成了同步方法,并把刷新当前文档和重新进入登录界面的逻辑放在退出登录成功后的回调函数中实现
测试修改后的效果
修改前后端代码后我们就可以启动前后端项目进行测试,检验效果了!
我们登录成功之后进入项目主页面:
图 5 用户登录成功进入主页面
然后我们点击右上角的带有用户图标下面的小三角,在弹出的下拉框中点击Log Out
按钮后页面会弹出“退出登录成功”的消息提示后当前页面进入登录界面,同时后台也打印了“退出登录”的日志
图 6 退出登录后当前页面进入登录界面
用户登录与退出登录过程后台控制台打印出的日志信息
2021-12-11 11:46:30.641 INFO 8496 --- [nio-8081-exec-1] org.sang.service.UserService : 用户登录认证, username=heshengfu
2021-12-11 11:46:31.143 INFO 8496 --- [nio-8081-exec-3] o.s.controller.RouterResourceController : roleId=1
2021-12-11 11:46:31.241 INFO 8496 --- [nio-8081-exec-4] o.s.controller.RouterResourceController : roleId=1
2021-12-11 11:51:33.276 INFO 8496 --- [nio-8081-exec-9] org.sang.controller.UserController : 退出登录
写在最后
好了,自定义退出登录的bug已经完成了解决。这里不得不说对于spring-security中的很多功能,自己尚未解锁,之前的学习还只是入了个门而已,远未达到熟练的地步。但是在已解决问题和交付为第一要务的前提下,我们在踩到有关spring-security的坑时最好去参考以下一些使用spring-security作为项目中的安全控制模块且技术比较成熟的开源项目,参考行业内的大牛是怎么使用spring-security实现各种定制的功能的。这样对于我们解决项目中遇到的bug必定会起到事半功倍的效果。关于spring-security的学习,这里我推荐公众号【江南一点雨】发布的SpringSecurity
专辑文章,也可以购买他今年出版的热销技术书《深入浅出Spring Security》,也算是对作者长期耕耘java web
技术栈的一种支持。
最后附上本文的前后端项目代码仓库地址,有需要查看项目完整实现的读者可以自己把源码clone下来自行研究,修改退出登录失效Bug后的代码也都已经提交到了我的个人gitee代码仓库。
后端项目blogserver项目gitee地址:https://gitee.com/heshengfu1211/blogserver.git
前端vue-element-admin项目gitee地址:https://gitee.com/heshengfu1211/vue-element-admin.git
原创不易,希望进来的朋友都能在右下角点个【在看】,谢谢!
—END—
往期原创文章推荐
【1】SpringBoot项目拥抱Mybatis-Plus持久层框架实践,全面提升数据库层面开发效率!
【3】vue-element-admin整合SpringBoot实现动态渲染基于角色的菜单资源踩坑录(前后端整合篇)
【4】vue-element-admin整合spring-boot实现权限控制之用户管理篇
【5】vue-element-admin整合spring-boot权限设计之实现用户授权功能
【6】SpringBoot项目集成knif4j,从此告别手写Api文档
原文始发于微信公众号(阿福谈Web编程):解决一个粉丝反馈的spring-boot整合vue-element-admin项目出现的退出登录无效的Bug
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/42274.html