系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考,希望能帮助更多(Java)码农和想成为(Java)码农的人。
提示:尽量使用头条APP阅读,头条网页展示代码会有问题。
前面的文章我们实现了租房网平台的用户注册、用户登录、会话跟踪等功能,本篇文章继续实现用户的登出/退出功能。
实际上,我们之前的版本中,只要用户登录之后,在每个页面当中已经有退出按钮,如下图:
其对应的代码在我们的 include.jsp 中:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="houserenter.entity.House" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网</title>
</head>
<body>
<h1>你好,${sessionScope.userName}!欢迎来到租房网! <a href="login.html">退出</a></h1>
<br><br>
可以看到,这个退出按钮就是一个普通的链接,直接返回到登录页面而已。那这样有什么不好的地方呢?我们做这样一个实验:
结论就是这样简单的登录功能很不安全。
究其原因,其实是我们采用了session进行会话跟踪,只要session不过期,Servlet容器(我们这里是Tomcat)中的该session对象就还有效,绑定到该session对象中的数据也就还有效。
不过,因为HTTP是基于TCP的,所以不同的TCP连接肯定会产生不同的session,大家有兴趣的话可以自行测试一下TCP连接和session之间的关系。
所以,我们的用户退出功能必须是这样的:
Servlet容器感知用户的退出很简单,只要发送一个请求给Servlet容器即可。
所以我们设计一个用户退出的动作,让上面的退出按钮指向该动作:
<h1>你好,${sessionScope.userName}!欢迎来到租房网! <a href="logout.action">退出</a></h1>
我们可以在HouseRenterController中添加处理用户退出请求的动作:
@GetMapping("/logout.action")
public ModelAndView getLogout(HttpSession session) {
System.out.println("session: " + session);
System.out.println("session id: " + session.getId());
session.invalidate();
ModelAndView mv = new ModelAndView();
mv.setViewName("redirect:login.html");
return mv;
}
重点关注的是,我们调用了HttpSession的invalidate()方法,这样我们就销毁了该session。
我们是如何得知该方法的呢?我们可以充分利用IDE的自动补足功能,然后查看每一个方法的javadoc:
可以发现invalidate()方法就是用来使此session无效,并解除绑定到它的任何对象。
大家可以自行验证一下,经过这样改造后,上述问题得到解决。
ET+EF+MVC开发接口用户退出登陆接口和页面退出登陆实例,开发应用的时候都会遇到,笔者提供二个方法,以供参考:
一、接口 退出登陆方法
[HttpGet]
public HttpResponseMessage PA_ParentLogout(decimal ParentloginID, string UsrMp, string Token = null)
{
HttpResponseMessage result = null;
var ReturnStr = "{\"result\":\"" + (int)KeyEnum.AppReturn.失败 + "\",\"msg\":\"退出失败\",\"data\":\"\"}";
if (ParentloginID>0)
{
#region 验证token
if (!string.IsNullOrEmpty(Token))
{
int m = new WisdomStars.Bll.Api.Common().PUB_VerificationToken(Token);
if (m <= 0)
{
ReturnStr = "{\"result\":\"" + (int)KeyEnum.AppReturn.失败 + "\",\"msg\":\"登录失效\",\"data\":\"\"}";
result = new HttpResponseMessage { Content = new StringContent(ReturnStr, Encoding.GetEncoding("UTF-8"), "application/json") };
return result;
}
}
else
{
ReturnStr = "{\"result\":\"" + (int)KeyEnum.AppReturn.失败 + "\",\"msg\":\"token不能为空\",\"data\":\"\"}";
result = new HttpResponseMessage { Content = new StringContent(ReturnStr, Encoding.GetEncoding("UTF-8"), "application/json") };
return result;
}
#endregion 验证token
HashOperator operators1 = new HashOperator();
string key = Utils.GetDescription(KeyEnum.LoginUserCache.HXAppVaildParent) + UsrMp;
var ser = new ObjectSerializer();
ef.Configuration.ProxyCreationEnabled = false;
bool IsExist = operators1.Exist<string>(key, key);
if (IsExist == true)
{
//先删除redis中的key
operators1.Remove(key, key);
ReturnStr = "{\"result\":\"" + (int)KeyEnum.AppReturn.成功 + "\",\"msg\":\"退出成功\",\"data\":\"\"}";
#region 再清空手机token
ef.HX_Parentlogin.Where(a => a.ParentloginID == ParentloginID && a.GuardianTel == UsrMp).Update(p => new HX_Parentlogin
{
mobiletoken = "",
client = 0
});
#endregion 清空手机token
}
else
{
ReturnStr = "{\"result\":\"" + (int)KeyEnum.AppReturn.成功 + "\",\"msg\":\"退出成功\",\"data\":\"\"}";
#region 清空手机token
ef.HX_Parentlogin.Where(a => a.ParentloginID == ParentloginID && a.GuardianTel == UsrMp).Update(p => new HX_Parentlogin
{
mobiletoken = "",
client = 0
});
#endregion 清空手机token
}
}
result = new HttpResponseMessage { Content = new StringContent(ReturnStr, Encoding.GetEncoding("UTF-8"), "application/json") };
return result;
}
二、页面退出登陆方法,需要清除所有redis中的键值对。
#region 退出 + public ActionResult Logout()
public ActionResult Logout()
{
LoginInfo loginModel = Distribution.Common.Utils.GetAdminModel();
#region 获取登录信息
decimal adminUsrID = loginModel.adminUsrID;
var username = loginModel.Mobile.ToString();
#endregion 获取登录信息
if (adminUsrID > 0 && !string.IsNullOrEmpty(username))
{
#region 清除redis
HashOperator operators1 = new HashOperator();
var ser = new ObjectSerializer();
ef.Configuration.ProxyCreationEnabled = false;
HX_AdminUser m = ef.HX_AdminUser.Where(a=>a.adminUsrID== adminUsrID).AsNoTracking().FirstOrDefault();
string key = HX.Common.Utils.GetDescription(KeyEnum.LoginUserCache.HXDistributor) + username;
operators1.Remove(key);
string key2 = HX.Common.Utils.GetDescription(KeyEnum.LoginUserCache.HXDistributorCacheJurisdiction) + "_" + adminUsrID.ToString() + "_" + m.subsidiary_id.ToString();
operators1.Remove(key2);
#endregion 清除redis
HttpCookie aCookie = new HttpCookie("userInfo");
aCookie.Expires = DateTime.Now.AddDays(-1);
Response.AppendCookie(aCookie);
return Redirect("/Home/Login");
}
else
{
return Redirect("/Home/Login");
}
}
#endregion 退出
续之前完成的内容,首先创建一个常量类
常量类的内容
服务器端渲染
前后端分离
完成后台管理登录页面
进入前端静态资源
创建后台管理员登录页面admin-login.jsp
完成内容
然后完成页面跳转
配置mvc:view-controller
完成配置
启动服务访问一下
localhost:8080/learn-admin-webui/admin/to/login/page.html
修饰system-error.jsp
Md5加密工具方法
添加到类
编写代码
接着
测试下
*请认真填写需求信息,我们会在24小时内与您取得联系。