備忘錄《一》基於cookie使用攔截器實現客戶每次訪問自登陸一次

来源:http://www.cnblogs.com/zhaixiajiao/archive/2017/05/23/6892577.html
-Advertisement-
Play Games

原創聲明:本文為本人原創作品,絕非他處摘取,轉載請聯繫博主 相信大家在各大網站都會遇到,登錄時,在登錄框出現下次免登陸/一個月免登陸的類似選項,本次博文就是講解如何實現,在這記錄一下,也算是做個備忘錄合集,如果文中有錯,歡迎大家指出 為啥說自登陸一次呢,因為當訪問某個頁面時,如果第一次自動登錄失敗時 ...


原創聲明:本文為本人原創作品,絕非他處摘取,轉載請聯繫博主

相信大家在各大網站都會遇到,登錄時,在登錄框出現下次免登陸/一個月免登陸的類似選項,本次博文就是講解如何實現,在這記錄一下,也算是做個備忘錄合集,如果文中有錯,歡迎大家指出

為啥說自登陸一次呢,因為當訪問某個頁面時,如果第一次自動登錄失敗時,你下次刷新訪問時還再次走自動登錄流程,就會出現死迴圈。

本篇博文代碼示例框架為Spring MVC,下麵就講解實現該功能的需要掌握哪些知識:cookies與攔截器

1.cookies

我們看一下是如何保存cookies和如何刪除cookies

保存cookies

String newUserName = null;
try {
	newUserName = URLEncoder.encode(username, "UTF-8");//把用戶名轉碼,防止用戶名是中文,cookies保存中文取出會亂碼
} catch (UnsupportedEncodingException e) {
	e.printStackTrace();
}
Cookie nameCookie = new Cookie("username", newUserName);
String pwdMd5Cook = MD5Util.MD5(Pwd);
Cookie pwdCookie = new Cookie("pwd", pwdMd5Cook);// 保存加密後的密碼
nameCookie.setMaxAge(60 * 60 * 24 * 365);// 用戶名保存一年
pwdCookie.setMaxAge(60 * 60 * 24 * 30);// 密碼保存30天
// 發送Cookie信息到瀏覽器
response.addCookie(nameCookie);
response.addCookie(pwdCookie);

刪除cookies,刪除很簡單,但值得註意的時,刪除cookies,跟保存cookies一定要在同一個控制層,不然會找不到保存的cookies,導致刪除不了

Cookie cookie = new Cookie("pwd", null);
cookie.setMaxAge(0);// 刪除密碼cookie
response.addCookie(cookie);

2.攔截器

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class suicaiFilter implements Filter {
	@Override
	public void destroy() {
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req=(HttpServletRequest)request;
		HttpServletResponse res=(HttpServletResponse)response;
		HttpSession session = req.getSession();
		String requestURI = req.getRequestURI();
		String param = req.getQueryString();
		String url = req.getServletPath();
		if(param!=null){
			url = url+"?"+param;
		}
		if(requestURI.contains("js") || requestURI.contains("css") ||  requestURI.contains("images")){
			//不攔截css,js,images等靜態資源
			chain.doFilter(request, response);
		}else if(requestURI.contains("/info/")||requestURI.contains("/gys/")){
			//攔截前臺訪問頁面,跟前臺個人中心(供應商後臺),自動登錄一次,登錄不成功不進行操作,個人中心登錄不成功,則跳到登錄頁面
			ProviderInfo providerInfo = (ProviderInfo) session.getAttribute("providerInfo_gys");
			String IsAutomaticLogin = (String) session.getAttribute("IsAutomaticLogin");//是否已經走過自動登錄流程標識
			if(requestURI.contains("/info/") && !requestURI.contains("/login")){
				//訪問門戶等不需要必須登錄的(登錄除外),只嘗試登錄一次,如果不成功,不進行操作
				if(providerInfo==null && IsAutomaticLogin == null){
					req.getSession().setAttribute("goURL", url);
					res.sendRedirect(req.getContextPath() + "/common/automaticLogin");
				}else if(providerInfo==null && IsAutomaticLogin != null ){
					chain.doFilter(request, response);
				}else{
					chain.doFilter(request, response);
				}
			}else if(requestURI.contains("/gys/")){//訪問個人中心,自登陸一次,不成功跳轉到登錄頁面
				if(providerInfo==null && IsAutomaticLogin == null){
					req.getSession().setAttribute("goURL", url);
					res.sendRedirect(req.getContextPath() + "/common/automaticLogin");
				}else if(providerInfo==null && IsAutomaticLogin != null ){
					session.setAttribute("redirectUrl", url);
					res.sendRedirect(req.getContextPath() + "/login.jsp?redirectUrl="+url);
				}else{
					chain.doFilter(request, response);
				}
			}else{
				chain.doFilter(request, response);
			}
		}else{
			//不攔截
			chain.doFilter(request, response);
		}
	}
	@Override
	public void init(FilterConfig arg0) throws ServletException {
	}
}

從代碼中可知,需要一個是否已經自動登錄過的標識(IsAutomaticLogin),該標識是在走自動登錄時(不管成不成功)保存起來的

3.整體代碼展示

@Controller
@RequestMapping("/common")
public class CommonController{
	/**
	 * 自動登錄方法
	 * @param request
	 * @param response
	 * @param username
	 * @param pwd
	 * @param ProviderInfo 供應商賬戶信息model
	 * @return
	 */
	@RequestMapping("/automaticLogin")
	public String automaticLogin(HttpServletRequest request,ServletResponse response,@CookieValue(value = "username", required = false) String username,@CookieValue(value = "pwd", required = false) String pwd,ProviderInfo ProviderInfo) {
		// 保存需求登錄前的鏈接
		String goURL = (String) session.getAttribute("goURL");
		if (username == null) {//cookies中沒有用戶名,肯定不需要自動登錄
			session.setAttribute("IsAutomaticLogin", "0");
			return "redirect:" + goURL;
		} else {
			try {
				username = URLDecoder.decode(username, "UTF-8");//轉義,防止中文
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		// cookie失效 session一定為空,因為登錄時,一定會把用戶名保存在cookie中
		if ("".equals(username) || username == null) {// 使用session登錄不了,不進行任何操作,不在進入這個方法
			session.setAttribute("IsAutomaticLogin", "0");
			return "redirect:" + goURL;
		} else {
			// cookie中沒有密碼,判斷session為不為空,如果為空,說明沒有登錄,如果不為空,說明,用戶是選擇不記住密碼登錄(所以cookie中沒有密碼)
			if ("".equals(pwd) || pwd == null) {
				ProviderInfo customer1 = (ProviderInfo) session.getAttribute("providerInfo_gys");
				if (customer1 == null) {// 使用session登錄不了,不進行任何操作,不在進入這個方法
					session.setAttribute("IsAutomaticLogin", "0");
					return "redirect:" + goURL;
				} else {
					// 已經登錄,不再進入這個方法
					return "redirect:" + goURL;
				}
			} else {
				// cookie中有密碼,判斷session為不為空,如果為空,說明沒有登錄,如果不為空,說明已經登錄
				ProviderInfo customer1 = (ProviderInfo) session.getAttribute("providerInfo_gys");
				if (customer1 == null) {// 當前沒有登錄,調用cookies中的用戶名跟密碼進行登錄
					// 進行自動登錄操作,登錄成功後返回原來頁面
					ProviderInfo customer3 = ValidateDate(username);
					customer3.setPwd(pwd);
					customer3.setAccountType(6);
					ProviderInfo customer2 = infoService.login(customer3);//調用登錄方法
					if (customer2 == null) {// 自動登錄失敗,不再進入這個方法
						session.setAttribute("IsAutomaticLogin", "0");
						return "redirect:" + goURL;
					} else {
						// 登陸成功保存客戶信息到session
						session.setAttribute("providerInfo_gys",customer2);
						return "redirect:" + goURL;
					}
				} else {
					return "redirect:" + goURL;
				}
			}
		}
	}
	/**
	 * 用戶登陸
	 * @param request
	 * @param response
	 * @param cus
	 * @return
	 */
	@RequestMapping("/UserLogin")
	@ResponseBody
	public Map<String, Object> goLogin(HttpServletRequest request,HttpServletResponse response,@ModelAttribute("ProviderInfo") ProviderInfo cus) {
		/*省略一些邏輯判斷*/
		cus.setPwd(MD5Util.MD5(Pwd));
		ProviderInfo providerInfo = infoService.login(cus);
		Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
		if (providerInfo == null) {
			// 登陸失敗,重新跳轉到登陸頁面
			map.put("error", "密碼錯誤");
			return map;
		}else{
			String newUserName = null;
			if (remember_me.equals("1")) {// 有選擇一個月免登錄
				try {
					newUserName = URLEncoder.encode(username, "UTF-8");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				Cookie nameCookie = new Cookie("username", newUserName);
				String pwdMd5Cook = MD5Util.MD5(Pwd);
				Cookie pwdCookie = new Cookie("pwd", pwdMd5Cook);// 保存加密後的密碼+"create"
				nameCookie.setMaxAge(60 * 60 * 24 * 365);// 用戶名保存一年
				pwdCookie.setMaxAge(60 * 60 * 24 * 30);// 密碼保存30天
				// 發送Cookie信息到瀏覽器
				response.addCookie(nameCookie);
				response.addCookie(pwdCookie);
				session.setAttribute("IsAutomaticLogin",null);
			}else{//沒有選擇,刪除上次可能已經選擇自動登錄時的密碼
				Cookie[] cookies = request.getCookies();
				if (null != cookies) {
					for (Cookie cookie : cookies) {
						cookieMap.put(cookie.getName(), cookie);
					}
				}
				if (cookies != null) {
					for (int i = 0; i < cookies.length; i++) {
						if (cookieMap.containsKey("pwd")) {
							Cookie cookie = new Cookie("pwd", null);
							cookie.setMaxAge(0);// 刪除密碼cookie
							response.addCookie(cookie);
						}
					}
				}
			}
			// 登陸成功,保存當前user信息,保存客戶信息到session
			map.put("ProviderInfo", providerInfo);
			map.put("goURL", session.getAttribute("goURL"));
			session.setAttribute("providerInfo_gys", providerInfo);
			return map;
		}else {
			map.put("error", "該供應商賬號不存在");
			return map;
		}
	}
	/**
	 * 註銷
	 * @return
	 */
	@RequestMapping("/logout")
	public String logout(HttpServletResponse response) {
		Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
		Cookie[] cookies = request.getCookies();
		if (null != cookies) {
			for (Cookie cookie : cookies) {
				cookieMap.put(cookie.getName(), cookie);
			}
		}
		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				if (cookieMap.containsKey("pwd")) {
					Cookie cookie = new Cookie("pwd", null);
					cookie.setMaxAge(0);// 刪除密碼cookie
					response.addCookie(cookie);
				}
			}
		}
		session.setAttribute("providerInfo_gys", null);
		return "/index";
	}
}

到此,該功能示例講解全部完成,如有不對的地方,歡迎大家在評論區指出。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文章是在VS2017的環境下,.net core 1.1版本以上。 在這期間,由於.net core 並不基於IIS,我們的過去的網路請求代碼在.net core框架下,有可能會出現不相容,報錯的現象。這裡大致介紹下在.net core 下如何進行http請求,主要仍然是GET和POST方法,有錯 ...
  • Netop.Core主要提供的服務是類工廠服務及AOP服務,當然還其它一些小服務: 一、對話上下文Netop.Core.Context.SessionContext 此對話上下文可用在桌面程式和ASP.NET程式,可用SetData和GetData在上下文中傳遞數據。方法有: public stat ...
  • 參考文章:http://www.cnblogs.com/zhuyongblogs/p/5752638.html http://www.cnblogs.com/knowledgesea/p/5145239.html ...
  • 一、概述 1、quartz.net 是一款從java quartz 上延伸出來的定時任務框架。 2、我在網上看到很多大神寫過關於quartz.net 的博客、文章等,在這些博客文章里也學會了很多關於quartz的知識。今天博主也想寫一篇關於quartz的文章(不足之處望大神斧正),希望能幫助正在學習 ...
  • 1. 新建一個配置文件log4net.config,配置方法同成web.config或app.config一致; <?xml version="1.0" encoding="utf-8"?><configuration> <configSections> <section name="log4net ...
  • 簡言 本人在博客園註冊也2年多了,一直沒有寫自己的博客,因為才疏學淺一直跟著園子里的大哥們學習這.net技術。一年之前跳槽到現在的公司工作,由於公司沒有自己一套的開發框架,每次都要重新搭建,於是本人就用業餘時間寫了一個簡單開發框架,我也不知道叫“框架”是否符合,大家對付著看吧,希望可以幫助一些新人學 ...
  • using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;u ...
  • 簡介 RabbitMQ是用erlang開發的,集群非常方便,因為erlang天生就是一門分散式語言,但其本身並不支持負載均衡。 Rabbit模式大概分為以下三種:單一模式、普通模式、鏡像模式 RabbitMQ工作模式 單一模式 (最簡單的情況,非集群模式) 普通模式 (預設的集群模式) 流程 對於Q ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...