備忘錄《一》基於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);// 刪除密碼cookieresponse.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 {@Overridepublic void destroy() {}@Overridepublic 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);}}@Overridepublic 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 {// 登陸成功儲存客戶資訊到sessionsession.setAttribute("providerInfo_gys",customer2);return "redirect:" + goURL;}} else {return "redirect:" + goURL;}}}}/** * 使用者登陸 * @param request * @param response * @param cus * @return */@RequestMapping("/UserLogin")@ResponseBodypublic 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);// 刪除密碼cookieresponse.addCookie(cookie);}}}}// 登陸成功,儲存當前user資訊,儲存客戶資訊到sessionmap.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);// 刪除密碼cookieresponse.addCookie(cookie);}}}session.setAttribute("providerInfo_gys", null);return "/index";}}
到此,該功能樣本講解全部完成,如有不對的地方,歡迎大家在評論區指出。