原创声明:本文为本人原创作品,绝非他处摘取,转载请联系博主

相信大家在各大网站都会遇到,登录时,在登录框出现下次免登陆/一个月免登陆的类似选项,本次博文就是讲解如何实现,在这记录一下,也算是做个备忘录合集,如果文中有错,欢迎大家指出

为啥说自登陆一次呢,因为当访问某个页面时,如果第一次自动登录失败时,你下次刷新访问时还再次走自动登录流程,就会出现死循环。

本篇博文代码示例框架为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";
	}
}

到此,该功能示例讲解全部完成,如有不对的地方,欢迎大家在评论区指出。

备忘录《一》基于cookie使用拦截器实现客户每次访问自登陆一次的更多相关文章

  1. 基于cookie使用过滤器实现客户每次访问自登陆一次

    原创声明:本文为本人原创作品,绝非他处摘取,转载请联系博主 相信大家在各大网站都会遇到,登录时,在登录框出现下次免登陆/一个月免登陆的类似选项,本次博文就是讲解如何实现,在这记录一下,也算是做个备忘录 ...

  2. AOP框架Dora.Interception 3.0 [5]: 基于策略的拦截器注册方式

    注册拦截器旨在解决如何将拦截器应用到目标方法的问题.在我看来,针对拦截器的注册应该是明确而精准的,也就是我们提供的注册方式应该让拦截器准确地应用到期望的目标方法上,不能多也不能少.如果注册的方式过于模 ...

  3. AOP框架Dora.Interception 3.0 [4]: 基于特性的拦截器注册

    按照单一职责的原则,拦截器只负责需要的拦截操作的执行,至于它采用何种方式应用到目标方法上,以及它在整个拦截器管道中的位置则属于“拦截器注册”的范畴.Dora.Interception提供了几种典型的注 ...

  4. java端拦截器判断客户的的请求是否是ajax请求

    java端拦截器判断客户的的请求是否是ajax请求 发表于 2014-08-22 23:38:08 普通请求与ajax请求的报文头不一样,通过如下 String requestType = reque ...

  5. spring mvc 用cookie和拦截器实现自动登录(/免登录)

    Cookie/Session机制详解:http://blog.csdn.net/fangaoxin/article/details/6952954 SpringMVC记住密码功能:http://blo ...

  6. springMvc基于注解登录拦截器

    1.首先先定义一个拦截器注解 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) p ...

  7. SpringBoot静态资源访问+拦截器+Thymeleaf模板引擎实现简单登陆

    在此记录一下这十几天的学习情况,卡在模板引擎这里已经是四天了. 对Springboot的配置有一个比较深刻的认识,在此和大家分享一下初学者入门Spring Boot的注意事项,如果是初学SpringB ...

  8. django之基于cookie和装饰器实现用户认证

    示例1 # Create your views here. user = "a" pwd = "a" def login(request): if reques ...

  9. spring boot j集成seagger 加入拦截器后 swagger 不能访问

    一开始我是这样排除拦截的,但是发现没用 后来我发现swagger的真实访问路径是这样的 转自: https://blog.csdn.net/ab1991823/article/details/7906 ...

随机推荐

  1. 万能数据库连接类-Oracle、DB2 、Access 、Sql Server

    package cc.apps.report;   import java.sql.Connection; import java.sql.DriverManager; import java.sql ...

  2. 在应用程序中使用Xml文件

    用于操作Xml的文档主要有XmlNode.XmlDocument.XmlComment.XmlElement.XmlAttribute.XmlText.XmlNodeList 下面用一段代码来具体说明 ...

  3. JS滚动加载

    var one = true;//设置一个全局变量 $(window).scroll(function () { var hight = document.body.scrollHeight - do ...

  4. 实现简单的跨站脚本攻击(XSS)

    我们来通俗的了解一下什么是跨站脚本攻击(XSS):在表单中提交 一段 js代码 ,提交的内容被展示到页面时 ,js会被浏览器解析 打个比方吧,比如我现在写的这篇博客,写完以后我要发表对吧? 发表这个过 ...

  5. 关于constraint的用法

    1.主键约束:要对一个列加主键约束的话,这列就必须要满足的条件就是非空因为主键约束:就是对一个列进行了约束,约束为(非空.不重复)以下是代码  要对一个列加主键,列名为id,表名为emp格式为:alt ...

  6. 图文详解如何快捷搭建LNMP服务环境

    上一篇与大家一起学习了下如何搭建LAMP环境的知识,今天小编再和大家分享下如何快捷地搭建LNMP环境,并搭建起一个网站.Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/S ...

  7. 通过web对.exe程序进行更新和修改

    实现功能:通过网站更新用户的软件,需要联网,也可以通过本地网站更新局域网用户软件. 根本实现:1.一个网站(我用的是自己的www.aq36.xyz ,本地就可以,可以用localhost)然后运行up ...

  8. Unity C# 多态 委托 事件 匿名委托 Lambda表达式 观察者模式 .NET 框架中的委托和事件

    一.多态 里氏替换原则: 任何能用基类的地方,可以用子类代替,反过来不行.子类能够在基类的基础上增加新的行为.面向对象设计的基本原则之一. 开放封闭原则: 对扩展开放,意味着有新的需求或变化时,可以对 ...

  9. Java排序算法之希尔(Shell)排序

    基本思想: 希尔排序就是对直接插入排序的一个优化.现在有一个array,希尔排序就是设定一个增量incrementNum(0<incrementNum<array.length).先从ar ...

  10. iOS开发 socket, 全局socket

    因为项目的要求是全局的socket,  哪里都有可能使用到socket去发消息, 所以我把socket写在了单利里面 项目用的是 pod 'CocoaAsyncSocket'  三方库, 是异步的, ...