1. 程式人生 > >備忘錄《一》基於cookie使用過濾器實現客戶每次訪問自登陸一次

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

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

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

本篇博文程式碼示例框架為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";
	}
}
到處,該功能示例講解全部完成,如有不對的地方,歡迎大家在評論區指出。