-
2022-01-09 08:10:27
给退出登录按钮logoutBtn添加点击监听事件
1、在点击事件中,确认退出
// 弹窗确认退出 if(!window.confirm('确认退出吗')) return
2、确认退出后,删除用户本地id和token
// 删除本地token localStorage.removeItem('token') localStorage.removeItem('id')
3、向后台发送退出登录的请求
// 发送退出登录请求 await pAjax({ url:'http://localhost:8888/users/logout', data:{id} })
4、退出登录请求发送完毕后,刷新页面
// 刷新页面 location.reload();
更多相关内容 -
Android应用退出登录的实现方法
2020-08-30 19:16:51每一个app都会有一个”退出登陆”的功能,当点击退出之后需要将所有的Activity都finish掉,开始是想将栈中的所有Activity清除掉,但是没有找到...下面小编给大家分享android应用退出登录的实现方法,需要的朋友参考下 -
退出登录 - SpringSecurity框架实现用户退出登录-附件资源
2021-03-02 15:06:19退出登录 - SpringSecurity框架实现用户退出登录-附件资源 -
WPF10分钟不操作就自动退出登录
2020-09-16 15:42:24启动任务线程:默认10分钟不操作即注销退出 Task.Factory.StartNew(() => { while (isMonitor) { if (DateTime.Now.Subtract(GlobalUtil.LastOperateTime).TotalMinutes >= GlobalUtil.AdminTimeoutMinute) { ... -
windows共享目录-退出登录 bat脚本-
2017-07-14 09:48:32windowsNT系统连接共享目录后,如果不小心点击了记住密码,想要退出账户,比较麻烦,使用此脚本,双击退出。 -
uniapp——获取退出登录
2022-01-12 13:46:18JSON.parse(userinfo) if (userInfo) { state.userInfo = userInfo state.token = userInfo.token state.status = userInfo.status } }, 进行设置 在app.vue中写入 接下来是点击退出登录按钮后...对vuex进行封装
index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) import cart from './modules/cart.js' // import user from './modules/user.js' let store = new Vuex.Store({ modules:{ cart, } }) export default store
cart.js
export default { state: { list: [ { checked: false, id: 11, title: "商品标题111", cover: "/static/images/demo/list/1.jpg", // 选中商品属性 attrs: [{ title: "颜色", selected: 0, list: [{ name: '火焰红', }, { name: '炭黑', }, { name: '冰川兰', } ] }, { title: "容量", selected: 0, list: [{ name: '64GB', }, { name: '128GB', }, ] }, { title: "套餐", selected: 0, list: [{ name: '标配', }, { name: '套餐一', }, { name: '套餐二', } ] }, ], pprice: 336, num: 1, minnum: 1, maxnum: 10, // 该商品最大商品数,跟库存有关 }, { checked: false, id: 12, title: "商品222", cover: "/static/images/demo/list/1.jpg", // 选中商品属性 attrs: [{ title: "颜色", selected: 0, list: [{ name: '火焰红', }, { name: '炭黑', }, { name: '冰川兰', } ] }, { title: "容量", selected: 0, list: [{ name: '64GB', }, { name: '128GB', }, ] }, { title: "套餐", selected: 0, list: [{ name: '标配', }, { name: '套餐一', }, { name: '套餐二', } ] }, ], pprice: 200, num: 1, minnum: 1, maxnum: 10, // 该商品最大商品数,跟库存有关 }, { checked: false, id: 13, title: "商品标题333", cover: "/static/images/demo/list/1.jpg", // 选中商品属性 attrs: [{ title: "颜色", selected: 0, list: [{ name: '火焰红', }, { name: '炭黑', }, { name: '冰川兰', } ] }, { title: "容量", selected: 0, list: [{ name: '64GB', }, { name: '128GB', }, ] }, { title: "套餐", selected: 0, list: [{ name: '标配', }, { name: '套餐一', }, { name: '套餐二', } ] }, ], pprice: 100, num: 2, minnum: 1, maxnum: 10, // 该商品最大商品数,跟库存有关 } ], selectedAll:[]//储存选中数据 }, getters: { //购物车为空 disSelect(state){ return state.list.length === 0; }, //全部选中 checkedAll(state){ return state.list.length === state.selectedAll.length }, //计算总价 totalPrice(state){ let total = 0 state.list.forEach(v=>{ /* if(state.selectedAll.indexOf(v.id)!=-1){ total += v.pprice * v.num } */ console.log(v.num); if(v.checked){ total += v.pprice * v.num } }) return total }, //合计按钮不可用状态 disabled(state){ if(state.list.length===0){ state.list.checked = false return true } } }, mutations: { //单选 selectItem(state,index){ var id = state.list[index].id var i = state.selectedAll.indexOf(id) if (i > -1) { // 取消当前商品选中状态 state.list[index].checked = false // 移除选中列表中的当前商品 return state.selectedAll.splice(i,1) } // 选中 state.list[index].checked = true state.selectedAll.push(id) console.log(state.selectedAll); }, //全选 selectAll(state){ /* 方法一 */ state.selectedAll=[]/* 清空以前的全中的内容 */ state.list.map(v=>{ v.checked = true state.selectedAll.push(v.id) }) /* 方法二 */ /* state.selectedAll = state.list.map(v=>{ v.checked = true return v.id }) */ }, //全不选 noselectAll(state){ state.list.map(v=>{ v.checked = false }) state.selectedAll = [] }, //删除商品 delgoods(state){ state.list = state.list.filter(v=>{ console.log(state.selectedAll.indexOf(v.id) === -1); return state.selectedAll.indexOf(v.id) === -1 }) state.selectedAll = []//清空id } }, actions: { //全选 /* doselectAll(context){ console.log(context); context.getters.checkedAll?context.commit('noselectAll'):context.commit('selectAll') } */ doselectAll({getters,commit}){ getters.checkedAll?commit('noselectAll'):commit('selectAll') }, dodelgoods({commit}){ uni.showModal({ content:'您确定要删除吗', success: () => { commit('delgoods') }, fail: (err) => { console.log(err); } }) } } }
user.js
import $H from "@/utils/request.js" export default { state:{ token:false, status:false, userInfo:{} }, mutations:{ }, getters:{}, action:{}, }
在myfile中引入vuex
import {mapState} from 'vuex'
computed:{ ...mapState({ userInfo:state=>state.user.userInfo, }) }
对标签进行判断
{{userInfo.nickname?userInfo.nickname:'登陆/注册'}}
点击登陆时获取数据
mutations: { //登录获取数据并储存到vuex login(state, userInfo) { state.userInfo = userInfo //res.data.data state.token = userInfo.token state.status = userInfo.status console.log(userInfo.nickname); }, },
在login页面引入
import {mapMutations} from 'vuex' ...mapMutations(['login']),
这时刷新页面时会丢失数据,这里需要本地存储
写个方法用来得到数据
initUser(state) { let userinfo = uni.getStorageSync('userInfo') let userInfo = JSON.parse(userinfo) if (userInfo) { state.userInfo = userInfo state.token = userInfo.token state.status = userInfo.status } },
进行设置
在app.vue中写入
接下来是点击退出登录按钮后清空数据
loginOut(state){ state.userInfo = {} state.token = false state.status = false uni.removeStorageSync('userInfo') }
因为删除数据需要返回给后端,不能直接在表面上删除,所以需要用到删除接口
header: options.header || {},
actions: { layout(context){ let userinfo = uni.getStorageSync('userInfo') let userInfo = JSON.parse(userinfo) let token = userInfo.token console.log(context); $H({ url:'/logout', method:'POST', data:{}, header:{ token } }) context.commit('loginOut') } }
另一种方法:
在request.js中引入store
import $store from "@/store/index.js"
if (options.header) { console.log($store); options.header.token = $store.state.user.token // 二次验证(拦截器) if (options.checkToken && !options.header.token) { uni.showToast({ title: '请先登录', icon: 'none' }); return uni.navigateTo({ url: '/pages/login/login', }); } }
第三种方法:
-
Java实现登录功能(含修改密码 退出登录等)
2021-07-07 14:15:581.登录页面如图 2.业务准备 2.1.用户实体类 public class User { /** * 用户ID */ private Integer id; /** * 用户账号 */ private String userCode; /** * 用户名 */ private String userName; /** ...1.登录页面如图
2.业务准备
2.1.用户实体类
public class User { /** * 用户ID */ private Integer id; /** * 用户账号 */ private String userCode; /** * 用户名 */ private String userName; /** * 用户密码 */ private String password; /** * 用户类型 */ private String typeCode; /** * 用户所属组(科室、公司等) */ private String groupCode; /** * 用户地址 */ private String address; /** * 手机号 */ private String mobile; /** * 电话号码 */ private String phoneNum; /** * 邮箱 */ private String eMail; /** * 用户角色 */ private Integer roleId; /** * 锁定状态1:未锁定2:锁定 */ private Integer userLock; /** * 锁定时间 */ private Date gmtUserLock; /** * 用户更新日期 */ private Date gmtModified; /** * 创建时间 */ private Date gmtCreated; /** * 删除状态 */ private Integer isDel; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserCode() { return userCode; } public void setUserCode(String userCode) { this.userCode = userCode; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getTypeCode() { return typeCode; } public void setTypeCode(String typeCode) { this.typeCode = typeCode; } public String getGroupCode() { return groupCode; } public void setGroupCode(String groupCode) { this.groupCode = groupCode; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getEMail() { return eMail; } public void setEMail(String eMail) { this.eMail = eMail; } public Integer getRoleId() { return roleId; } public void setRoleId(Integer roleId) { this.roleId = roleId; } public Integer getUserLock() { return userLock; } public void setUserLock(Integer userLock) { this.userLock = userLock; } public Date getGmtUserLock() { return gmtUserLock; } public void setGmtUserLock(Date gmtUserLock) { this.gmtUserLock = gmtUserLock; } public Date getGmtModified() { return gmtModified; } public void setGmtModified(Date gmtModified) { this.gmtModified = gmtModified; } public Date getGmtCreated() { return gmtCreated; } public void setGmtCreated(Date gmtCreated) { this.gmtCreated = gmtCreated; } public Integer getIsDel() { return isDel; } public void setIsDel(Integer isDel) { this.isDel = isDel; } }
2.2.创建用户表
此处只展示用户表 若需要全部角色菜单等表私信或评论
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID', `user_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '用户账号', `user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '用户名', `password` varchar(35) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '用户密码', `type_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '用户类型', `group_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '用户所属组(科室、公司等)', `address` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT '用户地址', `mobile` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '手机号', `phone_num` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '电话号码', `e_mail` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '邮箱', `role_id` int(11) NULL DEFAULT NULL COMMENT '用户角色', `user_lock` int(1) NOT NULL COMMENT '锁定状态1:未锁定2:锁定', `gmt_user_lock` datetime(0) NULL DEFAULT NULL COMMENT '锁定时间', `gmt_modified` datetime(0) NOT NULL COMMENT '用户更新日期', `gmt_created` datetime(0) NOT NULL COMMENT '创建时间', `is_del` int(1) NOT NULL DEFAULT 1 COMMENT '删除状态 1正常 2删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '系统用户表' ROW_FORMAT = Dynamic;
3.登录业务实现
3.1.Controller
@RequestMapping("dologin") @ResponseBody public Response dologin(UserDto user, HttpServletRequest request) { Integer flag = -1; JSONObject json = new JSONObject(); do { if (StringUtils.isEmpty(user.getUserCode()) || StringUtils.isEmpty(user.getPassword())) { // 用户信息不完整; break; } // 判断用户是否存在 User userResult=new User(); userResult.setUserCode(user.getUserCode()); User usertemp = userService.findOne(userResult, null); try { if (usertemp == null) { // 账号不存在的场合 flag = 0; json.put("flag", flag); break; } user.setPassword(MD5Utils.md5Encode(user.getPassword())); if (!user.getPassword().equals(usertemp.getPassword())) { // 密码错误的场合 flag = 1; json.put("flag", flag); json.put("account", usertemp.getUserCode()); } else { if (usertemp.getIsDel() == 3) { flag = 4; json.put("flag", flag); } else { JSONObject jsonList = new JSONObject(); if(usertemp.getRoleId()!=null){ //单一角色 jsonList = menuService.queryMenuByRole(Integer.valueOf(usertemp.getRoleId())); } if (jsonList != null && jsonList.size() != 0 &&jsonList.getJSONArray("@menu@000").size() > 0) { // 成功登录 HttpSession session = request.getSession(); // 存储用户到session session.setAttribute(Constant.SESSION_USER, usertemp); session.setAttribute("menu", jsonList); flag = 3; json.put("flag", flag); } else { //无一级菜单权限 flag = 2; json.put("flag", flag); } } } } catch (Exception e) { e.printStackTrace(); } } while (false); json.put("flag", flag); return Response.success(json); }
3.2.Service+ServiceImpl+Dao
/** *@Description 通过角色查询菜单表数据 *@param *@return *@author wang hq */ JSONObject queryMenuByRole(Integer roleId);
@Override public JSONObject queryMenuByRole(Integer roleId) { return setMenuJson(menuDao.queryMenuByRole(roleId)); }
/** *@Description 通过角色查询菜单 *@param *@return *@author wang hq */ List<MenuDto> queryMenuByRole(@Param("roleId") Integer roleId);
3.3.Mapper
<select id="queryMenuByRole" resultMap="menuDtoMap" parameterType="java.lang.Integer"> SELECT DISTINCT m.id id, m.menu_parent_code menu_parent_code, m.menu_name menu_name, m.menu_code menu_code, m.url url, m.img img, m.sort sort, m.button_type button_type FROM menu m INNER JOIN role_relate_menu rrm ON rrm.menu_id = m.id AND rrm.is_del = 1 WHERE m.is_del = 1 AND rrm.role_id = #{roleId} ORDER BY menu_parent_code,sort </select>
3.4.点击登录按钮结果展示
3.4.1.flag为3即为登录成功
3.4.2.页面也已登录成功
4.修改密码
4.1.Controller
// 修改密码 @RequestMapping("updatePassword") @ResponseBody public Response updatePassword(HttpServletRequest request, String oldPassword, String newPassword) { Integer flag = -1; JSONObject json = new JSONObject(); User user = (User) request.getSession().getAttribute(Constant.SESSION_USER); if (StringUtils.isNotEmpty(oldPassword)) { try { String psw = MD5Utils.md5Encode(oldPassword); if (psw.equals(user.getPassword())) { newPassword = MD5Utils.md5Encode(newPassword); User user1 = new User(); user1.setId(user.getId()); user1.setPassword(newPassword); flag = userService.update(user1); HttpSession session = request.getSession(); user.setPassword(newPassword); session.setAttribute(Constant.SESSION_USER, user); if (flag > 0) { flag = 2;// 修改成功 } } else { flag = 0;// 旧密码错误 } } catch (Exception e) { e.printStackTrace(); } } json.put("flag", flag); return Response.success(json); }
4.2.Service+ServiceImpl+Dao
Integer update(User user);
@Override public Integer update(User user) { return userDao.update(user); }
Integer update(User user);
4.3.Mapper
<update id="update"> update user <trim prefix="set" suffixOverrides=","> <if test="id != null"> id = #{id}, </if> <if test="userCode != null and ''!= userCode"> user_code = #{userCode}, </if> <if test="userName != null and ''!= userName"> user_name = #{userName}, </if> <if test="password != null and ''!= password"> password = #{password}, </if> <if test="typeCode != null and ''!= typeCode"> type_code = #{typeCode}, </if> <if test="groupCode != null and ''!= groupCode"> group_code = #{groupCode}, </if> <if test="address != null and ''!= address"> address = #{address}, </if> <if test="mobile != null and ''!= mobile"> mobile = #{mobile}, </if> <if test="phoneNum != null and ''!= phoneNum"> phone_num = #{phoneNum}, </if> <if test="eMail != null and ''!= eMail"> e_mail = #{eMail}, </if> <if test="roleId != null"> role_id = #{roleId}, </if> <if test="userLock != null"> user_lock = #{userLock}, </if> <if test="gmtUserLock != null"> gmt_user_lock = #{gmtUserLock}, </if> gmt_modified=now(), <if test="gmtCreated != null"> gmt_created = #{gmtCreated}, </if> <if test="isDel != null"> is_del = #{isDel}, </if> </trim> where id = #{id} </update>
4.4.测试
4.4.1.填写新密码与输入正确旧密码
4.4.2.点击确定确认修改密码
此时返回到登录页面重新输入新密码正确登录即可
5.退出登录
// 退出登录 @RequestMapping("loginOut") public String loginOut(HttpServletRequest request) { HttpSession session = request.getSession(); session.removeAttribute(Constant.SESSION_USER); return "redirect:/login"; }
至此 相应登录修改密码功能及代码讲解完毕 由于本文主要写后台业务代码实现 若需要前台页面Js等可私信或评论哦
-
解决一个粉丝反馈的spring-boot整合vue-element-admin项目出现的退出登录无效的Bug
2021-12-12 12:30:41花了一个晚上解决一个粉丝反馈的spring-boot整合vue-element-admin项目出现的退出登录无效的Bug引言
今年7-8月份的时候我连续发表了几篇spring-boot整合vue-element-admin项目实现自定义权限控制的实战文章,后面也受到了不少读者的点赞。后面自己也没注意去维护了,但是最近在CSDN上有一个粉丝还是一名高校教师突然给我留言说按照我的文章思路搭建了项目,也实现了自定义菜单和角色授权等功能。但是发现了一个很严重的bug,那就是退出登录无效,且退出登录后系统不会调到登录界面,点击其他页面也是一片空白。
图 1 读者反馈的项目退出登录失效bug据这位读者反馈,这个问题困扰了他一周了都没法解决,于是只好留言向我求助。本着帮粉丝解决问题的同时也是在提升自己的想法,于是我重新启动项目开启了这个自己放在一边很久项目的调试之路,同时也参考了之前的luban-mall前后端分离项目,花了一个晚上终于把问题解决了,这一刻自己又找到了一丢丢的成就感!好久没更新公众号,顺便也把解决前后端分离且使用spring-security作为安全框架的场景下自定义退出登录的具体实现。
1 找到前端退出登录按钮的实现逻辑并定位问题
首先我们得找到实现退出登录按钮代码的地方,它在
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适配器类中的代码了
2 后台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()方法会在应用上下文中清空当前用户的认证信息
3 修改前端退出登录逻辑
后端禁用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
项目中原作者的退出登录逻辑稍作了修改,这里我把异步方法改成了同步方法,并把刷新当前文档和重新进入登录界面的逻辑放在退出登录成功后的回调函数中实现4 测试修改后的效果
修改前后端代码后我们就可以启动前后端项目进行测试,检验效果了!
我们登录成功之后进入项目主页面:
图 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 : 退出登录
5 写在最后
好了,自定义退出登录的bug已经完成了解决。这里不得不说对于spring-security中的很多功能,自己尚未解锁,之前的学习还只是入了个门而已,远未达到熟练的地步。但是在已解决问题和交付为第一要务的前提下,我们在踩到有关spring-security的坑时最好去参考以下一些使用spring-security作为项目中的安全控制模块且技术比较成熟的开源项目,参考行业内的大牛是怎么使用spring-security实现各种定制的功能的。这样对于我们解决项目中遇到的bug必定会起到事半功倍的效果。关于spring-security的学习,这里我推荐公众号【江南一点雨】发布的SpringSecurity专辑文章,也可以购买他今年出版的热销技术书《深入浅出Spring Security》,也算是对作者长期耕耘java web技术栈的一种支持。
最后附上本文的前后端项目代码仓库地址,有需要查看项目完整实现的读者可以自己把源码clone下来自行研究,修改退出登录失效Bug后的代码也都已经提交到了我的个人gitee代码仓库。
后端项目blogserver项目gitee地址
前端vue-element-admin项目gitee地址本文首发个人微信公众号,欢迎还没关注我的CSDN的粉丝读者扫描下面的微信二维码,加个公众号关注,我会定期更新实战干货文章,有问题大家也可以加问哦微信给我留言,看到留言后我也会尽快安排时间尽我所能帮助各位粉丝读者解决。
-
VUE点击退出按钮退出登录,跳转至登录页面
2022-01-14 18:21:29实现一个简单的功能,点击页面右上角的退出按钮,跳转至登录页面,并需重新输入登录用户名和密码。 在登录的vue页面中,在标签处添加点击事件 <div class="quit" @click="quitLogin"></div> 在... -
Shiro的退出登录状态的方式
2020-10-15 11:44:52// 退出登录 //对所有用户认证 filterChainDefinitionMap.put("/**", "authc"); // 需登录才能访问 factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return factoryBean; } shiro会拦截/user/... -
java 实现session的退出登录
2022-01-22 17:32:20<a href="javascript:...退出登录</a> js文件 // 退出登录 function logout() { $.ajax({ async: false, type: "POST", url: '/logout', contentType: "application/x-www-form-urlencoded; charset= -
vue关闭浏览器退出登录
2021-11-30 21:41:42根据`beforeunload`和`unload`这两个事件实现关闭浏览器退出登录。 -
微软edge如何退出登录_如何更新Microsoft Edge
2020-09-23 00:16:09微软edge如何退出登录Microsoft 微软 Browser updates are important. Updates for Microsoft Edge deliver critical security patches, new features, and performance improvements. The Edge browser ... -
Java 删除session实现退出登录
2022-04-04 10:36:45JS代码: <script src="<%=path %>... //用户点击了 “退出登录”,java 清空 session $("#bu2").click(function () { res = confirm("你 确定要 退出 吗?"); //在页面上弹出对话框 if (res == t -
SpringSecurity 退出登录
2020-10-31 22:42:29退出登录 Spring Security默认的退出登录URL为/logout,退出登录后,Spring Security会做如下处理: 是当前的Sesion失效; 清除与当前用户关联的RememberMe记录; 清空当前的SecurityContext; 重定向到登录页。 ... -
瑞吉外卖项目:退出登录实现以及对登录功能完善
2022-04-24 20:49:35员工登录之后,页面跳转到后台首页(backend/index.html)此前会显示用户登录的用户名,点击退出按钮退出系统。 请求API 说明 值 请求地址URL employee/loginout 请求参数 无 返回参数 ... -
PHP实现退出登录功能
2020-02-09 10:25:16在PHP程序中,登录完成之后将存入session中,退出登录时,需要释放session,相应的代码如下所示。 <?php session_start(); if(isset($_SESSION["uid"])) // 检测变量是否设置 { session_unset(); // 释放当前在... -
用户退出登录,清空cookie
2020-09-06 09:44:37@ApiOperation(value = "用户退出登录",notes = "用户退出登录",httpMethod = "POST") @PostMapping("/logout") public IMOOCJSONResult logout(@RequestParam String userId, HttpServletRequest request, ... -
Android 退出登录实现
2019-07-09 21:39:00主要考虑的问题是资源的回收,如何在退出登录后回收 Activity 和 Fragment。 1、自定义一个工具类,该工具类拥有一个全局 List ,并且有添加、删除方法用于将 Activity 添加/移出List。 2、在父类 Activity 中去... -
web前端 用户退出登录方案(思路)
2021-12-20 22:12:11web前端 用户退出登录方案(思路) -
linux用户退出登录的命令介绍
2021-02-01 09:42:17linux用户退出登录的命令介绍发布时间:2020-06-09 15:51:29来源:亿速云阅读:395作者:元一linux本身就是bai基于命令行的系统,它的GUI像KDE之类du的是一套应用程序,这和Windows是不同的,很多初学者都不明白这个... -
如何实现关闭浏览器就能执行退出登录
2019-08-02 21:00:51## 前辈们,如何实现关闭浏览器就能执行退出登录 下面是关闭页面会执行方法,但我想要的是关闭浏览器 ``` ()"> function delSession() { alert("下面的ajax有运行无法弹出窗口"); $.ajax({ ... -
微信小程序 登录与退出登录
2021-02-02 13:57:04//判断用户的登录状态 this.globalData.loginPromise = getUserInfo().then(res => { if (res.data.code == 0) { this.globalData.isLogin = true; this.globalData.userInfo = res.data.data } else { //未登录 ... -
退出登录如何清除token
2021-09-08 22:47:46// 退出登录 function logout(){ // var logout = $('.logout'); // logout.click(function(){ $.ajax({ url: '/app/login/login_out', type: 'get', dataType: 'json', headers:{token:localStorage.getItem... -
JWT 的退出登录方法
2020-10-29 00:14:29凡是退出登录的token都放入黑名单中,定期清理。 每次用户请求服务器都校验token是否在黑名单 版本号校验 访问时从token中取出版本号和用户id 和 redis中存储 用户id和版本号 做对比,不一致则不给访问。 用户登出的... -
Laravel博客系统--退出登录
2020-09-11 10:19:17退出登录功能 1.定义一条退出登录路由 <?php use Illuminate\Support\Facades\Route; Route::group(['prefix'=>'admin','namespace'=>'Admin'],function (){ //登录 Route::match(['get','post'],'/','... -
页面长时间未操作,实现自动退出登录原理
2022-03-24 17:20:40页面长时间未操作,实现自动退出登录原理 -
在dropdown item中设置退出登录
2022-03-25 15:59:13给vue组件绑定事件时候,必须加上native ,否则会认为监听的是来自Item组件自定义的事件。 <el-dropdown-menu slot="dropdown"> <el-dropdown-item icon="el-icon-plus">...退出登录</el-dropdown