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

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

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

本篇博文代码示例框架为Spring MVC,下面就讲解实现该功能的需要掌握哪些知识:cookies与过滤器

1.cookies

何为Cookies:Cookies为 Web 应用程序保存用户相关信息提供了一种有用的方法。例如,当用户访问您的站点时,您可以利用 Cookie 保存用户首选项或其他信息,这样,当用户下次再访问您的站点时,应用程序就可以检索以前保存的信息。

我们看一下是如何保存cookies和如何删除cookies

  • 保存cookies
  1. String newUserName = null;
  2. try {
  3. newUserName = URLEncoder.encode(username, "UTF-8");//把用户名转码,防止用户名是中文,cookies保存中文取出会乱码
  4. } catch (UnsupportedEncodingException e) {
  5. e.printStackTrace();
  6. }
  7. Cookie nameCookie = new Cookie("username", newUserName);
  8. String pwdMd5Cook = MD5Util.MD5(Pwd);
  9. Cookie pwdCookie = new Cookie("pwd", pwdMd5Cook);// 保存加密后的密码
  10. nameCookie.setMaxAge(60 * 60 * 24 * 365);// 用户名保存一年
  11. pwdCookie.setMaxAge(60 * 60 * 24 * 30);// 密码保存30天
  12. // 发送Cookie信息到浏览器
  13. response.addCookie(nameCookie);
  14. response.addCookie(pwdCookie);

删除cookies,删除很简单,但值得注意的时,删除cookies,跟保存cookies一定要在同一个控制层,不然会找不到保存的cookies,导致删除不了

  1. Cookie cookie = new Cookie("pwd", null);
  2. cookie.setMaxAge(0);// 删除密码cookie
  3. response.addCookie(cookie);

2.Filter-过滤器

Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

实现方法:继承Filter接口,并实现其doFilter方法。在web.xml文件中对编写的filter类进行注册,并设置它所能拦截的资源

  1. <filter>指定一个过滤器。
  2. <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
  3. <filter-class>元素用于指定过滤器的完整的限定类名。
  4. <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
  5. 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
  6. <filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
  7. <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
  8. <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
  9. <servlet-name>指定过滤器所拦截的Servlet名称。
  10. <filter>
  11. <filter-name>suicaiFilter</filter-name>
  12. <filter-class>com.suicai.filter.suicaiFilter</filter-class>
  13. </filter>
  14.  
  15. <filter-mapping>
  16. <filter-name>suicaiFilter</filter-name>
  17. <url-pattern>/*</url-pattern>
  18. </filter-mapping>

下面看一下实际应用代码:

  1. public class suicaiFilter implements Filter {
  2. @Override
  3. public void destroy() {
  4. }
  5. @Override
  6. public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
  7. HttpServletRequest req=(HttpServletRequest)request;
  8. HttpServletResponse res=(HttpServletResponse)response;
  9. HttpSession session = req.getSession();
  10. String requestURI = req.getRequestURI();
  11. String param = req.getQueryString();
  12. String url = req.getServletPath();
  13. if(param!=null){
  14. url = url+"?"+param;
  15. }
  16. if(requestURI.contains("js") || requestURI.contains("css") || requestURI.contains("images")){
  17. //不过滤css,js,images等静态资源
  18. chain.doFilter(request, response);
  19. }else if(requestURI.contains("/info/")||requestURI.contains("/gys/")){
  20. //过滤前台访问页面,跟前台个人中心(供应商后台),自动登录一次,登录不成功不进行操作,个人中心登录不成功,则跳到登录页面
  21. ProviderInfo providerInfo = (ProviderInfo) session.getAttribute("providerInfo_gys");
  22. String IsAutomaticLogin = (String) session.getAttribute("IsAutomaticLogin");//是否已经走过自动登录流程标识
  23. if(requestURI.contains("/info/") && !requestURI.contains("/login")){
  24. //访问门户等不需要必须登录的(登录除外),只尝试登录一次,如果不成功,不进行操作
  25. if(providerInfo==null && IsAutomaticLogin == null){
  26. req.getSession().setAttribute("goURL", url);
  27. res.sendRedirect(req.getContextPath() + "/common/automaticLogin");
  28. }else if(providerInfo==null && IsAutomaticLogin != null ){
  29. chain.doFilter(request, response);
  30. }else{
  31. chain.doFilter(request, response);
  32. }
  33. }else if(requestURI.contains("/gys/")){//访问个人中心,自登陆一次,不成功跳转到登录页面
  34. if(providerInfo==null && IsAutomaticLogin == null){
  35. req.getSession().setAttribute("goURL", url);
  36. res.sendRedirect(req.getContextPath() + "/common/automaticLogin");
  37. }else if(providerInfo==null && IsAutomaticLogin != null ){
  38. session.setAttribute("redirectUrl", url);
  39. res.sendRedirect(req.getContextPath() + "/login.jsp?redirectUrl="+url);
  40. }else{
  41. chain.doFilter(request, response);
  42. }
  43. }else{
  44. chain.doFilter(request, response);
  45. }
  46. }else{
  47. //不过滤
  48. chain.doFilter(request, response);
  49. }
  50. }
  51. @Override
  52. public void init(FilterConfig arg0) throws ServletException {
  53. }
  54. }

从代码中可知,需要一个是否已经自动登录过的标识(IsAutomaticLogin),该标识是在走自动登录时(不管成不成功)保存起来的

3.结合上面提供知识,下面为整体代码展示,如发现不对地方,欢迎大家指出

  1. @Controller
  2. @RequestMapping("/common")
  3. public class CommonController{
  4. /**
  5. * 自动登录方法
  6. * @param request
  7. * @param response
  8. * @param username
  9. * @param pwd
  10. * @param ProviderInfo 供应商账户信息model
  11. * @return
  12. */
  13. @RequestMapping("/automaticLogin")
  14. public String automaticLogin(HttpServletRequest request,ServletResponse response,@CookieValue(value = "username", required = false) String username,@CookieValue(value = "pwd", required = false) String pwd,ProviderInfo ProviderInfo) {
  15. // 保存需求登录前的链接
  16. String goURL = (String) session.getAttribute("goURL");
  17. if (username == null) {//cookies中没有用户名,肯定不需要自动登录
  18. session.setAttribute("IsAutomaticLogin", "0");
  19. return "redirect:" + goURL;
  20. } else {
  21. try {
  22. username = URLDecoder.decode(username, "UTF-8");//转义,防止中文
  23. } catch (UnsupportedEncodingException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. // cookie失效 session一定为空,因为登录时,一定会把用户名保存在cookie中
  28. if ("".equals(username) || username == null) {// 使用session登录不了,不进行任何操作,不在进入这个方法
  29. session.setAttribute("IsAutomaticLogin", "0");
  30. return "redirect:" + goURL;
  31. } else {
  32. // cookie中没有密码,判断session为不为空,如果为空,说明没有登录,如果不为空,说明,用户是选择不记住密码登录(所以cookie中没有密码)
  33. if ("".equals(pwd) || pwd == null) {
  34. ProviderInfo customer1 = (ProviderInfo) session.getAttribute("providerInfo_gys");
  35. if (customer1 == null) {// 使用session登录不了,不进行任何操作,不在进入这个方法
  36. session.setAttribute("IsAutomaticLogin", "0");
  37. return "redirect:" + goURL;
  38. } else {
  39. // 已经登录,不再进入这个方法
  40. return "redirect:" + goURL;
  41. }
  42. } else {
  43. // cookie中有密码,判断session为不为空,如果为空,说明没有登录,如果不为空,说明已经登录
  44. ProviderInfo customer1 = (ProviderInfo) session.getAttribute("providerInfo_gys");
  45. if (customer1 == null) {// 当前没有登录,调用cookies中的用户名跟密码进行登录
  46. // 进行自动登录操作,登录成功后返回原来页面
  47. ProviderInfo customer3 = ValidateDate(username);
  48. customer3.setPwd(pwd);
  49. customer3.setAccountType(6);
  50. ProviderInfo customer2 = infoService.login(customer3);//调用登录方法
  51. if (customer2 == null) {// 自动登录失败,不再进入这个方法
  52. session.setAttribute("IsAutomaticLogin", "0");
  53. return "redirect:" + goURL;
  54. } else {
  55. // 登陆成功保存客户信息到session
  56. session.setAttribute("providerInfo_gys",customer2);
  57. return "redirect:" + goURL;
  58. }
  59. } else {
  60. return "redirect:" + goURL;
  61. }
  62. }
  63. }
  64. }
  65. /**
  66. * 用户登陆
  67. * @param request
  68. * @param response
  69. * @param cus
  70. * @return
  71. */
  72. @RequestMapping("/UserLogin")
  73. @ResponseBody
  74. public Map<String, Object> goLogin(HttpServletRequest request,HttpServletResponse response,@ModelAttribute("ProviderInfo") ProviderInfo cus) {
  75. /*省略一些逻辑判断*/
  76. cus.setPwd(MD5Util.MD5(Pwd));
  77. ProviderInfo providerInfo = infoService.login(cus);
  78. Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
  79. if (providerInfo == null) {
  80. // 登陆失败,重新跳转到登陆页面
  81. map.put("error", "密码错误");
  82. return map;
  83. }else{
  84. String newUserName = null;
  85. if (remember_me.equals("1")) {// 有选择一个月免登录
  86. try {
  87. newUserName = URLEncoder.encode(username, "UTF-8");
  88. } catch (UnsupportedEncodingException e) {
  89. e.printStackTrace();
  90. }
  91. Cookie nameCookie = new Cookie("username", newUserName);
  92. String pwdMd5Cook = MD5Util.MD5(Pwd);
  93. Cookie pwdCookie = new Cookie("pwd", pwdMd5Cook);// 保存加密后的密码+"create"
  94. nameCookie.setMaxAge(60 * 60 * 24 * 365);// 用户名保存一年
  95. pwdCookie.setMaxAge(60 * 60 * 24 * 30);// 密码保存30天
  96. // 发送Cookie信息到浏览器
  97. response.addCookie(nameCookie);
  98. response.addCookie(pwdCookie);
  99. session.setAttribute("IsAutomaticLogin",null);
  100. }else{//没有选择,删除上次可能已经选择自动登录时的密码
  101. Cookie[] cookies = request.getCookies();
  102. if (null != cookies) {
  103. for (Cookie cookie : cookies) {
  104. cookieMap.put(cookie.getName(), cookie);
  105. }
  106. }
  107. if (cookies != null) {
  108. for (int i = 0; i < cookies.length; i++) {
  109. if (cookieMap.containsKey("pwd")) {
  110. Cookie cookie = new Cookie("pwd", null);
  111. cookie.setMaxAge(0);// 删除密码cookie
  112. response.addCookie(cookie);
  113. }
  114. }
  115. }
  116. }
  117. // 登陆成功,保存当前user信息,保存客户信息到session
  118. map.put("ProviderInfo", providerInfo);
  119. map.put("goURL", session.getAttribute("goURL"));
  120. session.setAttribute("providerInfo_gys", providerInfo);
  121. return map;
  122. }else {
  123. map.put("error", "该供应商账号不存在");
  124. return map;
  125. }
  126. }
  127. /**
  128. * 注销
  129. * @return
  130. */
  131. @RequestMapping("/logout")
  132. public String logout(HttpServletResponse response) {
  133. Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
  134. Cookie[] cookies = request.getCookies();
  135. if (null != cookies) {
  136. for (Cookie cookie : cookies) {
  137. cookieMap.put(cookie.getName(), cookie);
  138. }
  139. }
  140. if (cookies != null) {
  141. for (int i = 0; i < cookies.length; i++) {
  142. if (cookieMap.containsKey("pwd")) {
  143. Cookie cookie = new Cookie("pwd", null);
  144. cookie.setMaxAge(0);// 删除密码cookie
  145. response.addCookie(cookie);
  146. }
  147. }
  148. }
  149. session.setAttribute("providerInfo_gys", null);
  150. return "/index";
  151. }
  152. }

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

基于cookie使用过滤器实现客户每次访问自登陆一次的更多相关文章

  1. 备忘录《一》基于cookie使用拦截器实现客户每次访问自登陆一次

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

  2. (26)基于cookie的登陆认证(写入cookie、删除cookie、登陆后所有域下的网页都可访问、登陆成功跳转至用户开始访问的页面、使用装饰器完成所有页面的登陆认证)

    获取cookie request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age ...

  3. 如何请求一个需要登陆才能访问的接口(基于cookie)---apipost

    在后台在开发.调试接口时,常常会遇到需要登陆才能请求的接口. 比如:获取登陆用户的收藏列表,此时,我们就需要模拟登陆状态进行接口调试了.如图: 今天,我们讲解利用ApiPost的环境变量,解决这种需要 ...

  4. 使用nginx sticky实现基于cookie的负载均衡

    在多台后台服务器的环境下,我们为了确保一个客户只和一台服务器通信,我们势必使用长连接.使用什么方式来实现这种连接呢,常见的有使用nginx自带的ip_hash来做,我想这绝对不是一个好的办法,如果前端 ...

  5. 使用nginx sticky实现基于cookie的负载均衡【转】

    在多台后台服务器的环境下,我们为了确保一个客户只和一台服务器通信,我们势必使用长连接.使用什么方式来实现这种连接呢,常见的有使用nginx自带的ip_hash来做,我想这绝对不是一个好的办法,如果前端 ...

  6. NGINX:sticky模块实现基于cookie的负载均衡

    Sticky模块 简述: 之前公司部署了一套网站及时发布系统,架构如下图所示:Nginx做前端代理,发布系统用tomcat运行,一台共享存储,一台数据库服务器:由于网站及时发布系统涉及到了用户登录操作 ...

  7. nginx第三方模块---nginx-sticky-module的使用(基于cookie的会话保持)

    目前的项目网站架构中使用了F5和nginx,F5用来做负载均衡,nginx只用作反向代理服务器.最近应客户的要求准备去掉F5,使用软负载.大家都知道nginx抗并发能力强,又可以做负载均衡,而且使用n ...

  8. Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录

    1.登录的实现 登录功能实现起来有哪些常用的方式,大家首先想到的肯定是cookie或session或cookie+session,当然还有其他模式,今天主要探讨一下在Asp.net core 2.0下 ...

  9. 基于 Cookie 的 SSO 中间件 kisso

    kisso  =  cookie sso 基于 Cookie 的 SSO 中间件,它是一把快速开发 java Web 登录系统(SSO)的瑞士军刀.欢迎大家使用 kisso !! kisso 帮助文档 ...

随机推荐

  1. 基于51单片机IIC通信的PCF8591学习笔记

    引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...

  2. std::thread使用

    本文将从以下三个部分介绍C++11标准中的thread类,本文主要内容为: 启动新线程 等待线程与分离线程 线程唯一标识符 1.启动线程 线程再std::threada对象创建时启动.最简单的情况下, ...

  3. 苹果笔记本只能上QQ,微信,任何浏览器不能打开网页的问题。

    我的笔记本一共遇到过两次这种情况.第一次是浏览器输入域名打不开网页,而输入ip地址可以打开.这就是DNS服务器的问题,解决方法很简单.在系统偏好设置里面找到网络,然后,点击正在连接的网络的高级选项,选 ...

  4. 【正常向】CODEVS上分黄金

    白银上分黄金失败=.= 在之前有很认真的写了一波排序,所以排序并不是很怂,还是那个理,现阶段学习的都是比较简单的排序,都是所谓的冒泡排序啊,桶排序这类,至于插排和选择排序,再往后又是什么快拍就很尬了. ...

  5. 洛谷【P2393】题解

    P2393 [yyy loves Maths II] 原题链接 话说,这题其实方法对了,也蛮水的. 首先方法是一样的,直接扩大忽略精度问题. 其次,我用了c++的函数控制输出小数位数,方法:cout& ...

  6. Xcode旧项目引入CocoaPod遇到的问题与解决

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  7. hdu1561 The more, The Better 树形DP+分组背包

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 思路: 典型的树形背包题目: 定义dp[i][j]表示以i为根节点,攻打j个城堡的获得的财宝的最 ...

  8. 为Distinct准备的通用对比器

    使用Linq过滤重复对象的时候,我们使用Distinct. 但是Distinct对int long等值类型才有效果,对于对象我们需要自己写个对象. 以下利用泛型封装了两个类: CommonCompar ...

  9. Java集合框架类

    java集合框架类图 Collection接口(List.Set.Queue.Stack):

  10. C#之自定义特性

    在前面介绍的代码中有使用特性,这些特性都是Microsoft定义好的,作为.NET Framework类库的一部分,许多特性都得到了C#编译器的支持. .NET Frmework也允许定义自己的特性. ...