整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          我的Java Web之路65 - 實現用戶登出/退出功能

          系列文章旨在記錄和總結自己在Java Web開發之路上的知識點、經驗、問題和思考,希望能幫助更多(Java)碼農和想成為(Java)碼農的人。

          提示:盡量使用頭條APP閱讀,頭條網頁展示代碼會有問題。

          目錄

          1. 介紹
          2. 原有的用戶退出功能
          3. 思路
          4. 修改include.jsp
          5. 添加處理用戶退出請求的動作
          6. 總結

          介紹

          前面的文章我們實現了租房網平臺的用戶注冊、用戶登錄、會話跟蹤等功能,本篇文章繼續實現用戶的登出/退出功能。

          原有的用戶退出功能

          實際上,我們之前的版本中,只要用戶登錄之后,在每個頁面當中已經有退出按鈕,如下圖:


          其對應的代碼在我們的 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>

          可以看到,這個退出按鈕就是一個普通的鏈接,直接返回到登錄頁面而已。那這樣有什么不好的地方呢?我們做這樣一個實驗:

          1. 先登錄到租房網平臺;
          2. 登錄后可以打開其他頁面,我這里假設打開某個房源詳情頁面,其URL是:http://localhost:8080/house-renter/house-details.action?houseId=1
          3. 然后點擊退出,會跳轉到登錄頁面;
          4. 此時我直接在瀏覽器的地址欄中重新輸入上述URL,可以新開一個瀏覽器標簽頁,甚至另外打開一個瀏覽器進程(不過必須是同一款瀏覽器,我這里是谷歌瀏覽器),敲回車;
          5. 結果是我跳過了登錄步驟,直接打開了該房源詳情頁面。

          結論就是這樣簡單的登錄功能很不安全。

          究其原因,其實是我們采用了session進行會話跟蹤,只要session不過期,Servlet容器(我們這里是Tomcat)中的該session對象就還有效,綁定到該session對象中的數據也就還有效。

          不過,因為HTTP是基于TCP的,所以不同的TCP連接肯定會產生不同的session,大家有興趣的話可以自行測試一下TCP連接和session之間的關系。

          思路

          所以,我們的用戶退出功能必須是這樣的:

          1. 用戶點擊退出按鈕;
          2. Servlet容器必須感知到用戶的退出;
          3. Servlet容器銷毀該用戶的session。

          修改include.jsp

          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無效,并解除綁定到它的任何對象。

          總結

          大家可以自行驗證一下,經過這樣改造后,上述問題得到解決。

          • 調用HttpSession的invalidate()方法可以使會話無效。

          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加密工具方法

          添加到類

          編寫代碼

          接著

          測試下


          主站蜘蛛池模板: 亚洲乱码一区二区三区国产精品| 亚洲国产精品一区二区久久hs| 亚洲综合一区二区精品导航| 亚洲一区二区视频在线观看| 久久精品亚洲一区二区三区浴池 | 国产一国产一区秋霞在线观看| 国产福利电影一区二区三区久久久久成人精品综合 | 久久久久久综合一区中文字幕| 午夜AV内射一区二区三区红桃视| 日本一区视频在线播放| 国产一区二区三区夜色 | 亚洲精品日韩一区二区小说| 国产婷婷色一区二区三区| 另类ts人妖一区二区三区| 精品国产乱子伦一区二区三区 | 亚洲无圣光一区二区| 无码欧精品亚洲日韩一区| 91精品国产一区二区三区左线| 国产成人无码一区二区在线观看| 精品一区二区三区高清免费观看 | 亚洲bt加勒比一区二区| 日韩av片无码一区二区不卡电影| 亚洲av高清在线观看一区二区 | 日韩久久精品一区二区三区| 国产福利一区二区| 在线不卡一区二区三区日韩| 国产成人亚洲综合一区| 在线视频一区二区日韩国产| 美女AV一区二区三区| 性色A码一区二区三区天美传媒| 精品人妻一区二区三区浪潮在线| 国产福利微拍精品一区二区| 插我一区二区在线观看| 国产成人一区二区三区电影网站| 国产精品亚洲专区一区| 午夜福利一区二区三区在线观看 | 亚洲乱码一区二区三区国产精品| 国产一区二区三区在线观看精品| 国产精品成人免费一区二区 | 亚洲bt加勒比一区二区| 久久精品国产一区二区|