系列文章旨在記錄和總結自己在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小時內與您取得聯系。