Home  >  Article  >  Backend Development  >  Detailed explanation of using filters to implement customer access login function based on cookies

Detailed explanation of using filters to implement customer access login function based on cookies

零下一度
零下一度Original
2017-06-15 13:52:091608browse

This article mainly introduces the use of filters based on cookies to enable customers to log in only once per visit. Friends who need it can refer to it

I believe everyone will encounter it on major websites. When logging in, when logging in, A similar option of no need to log in next time/no need to log in for one month will appear in the box. This article explains how to implement it. I record it here, which can be regarded as a collection of memos. If there is an error in the article, you are welcome to point out why

Self-login once, because when you visit a certain page, if the automatic login fails for the first time, you will go through the automatic login process again the next time you refresh the visit, and an infinite loop will occur.

The code example framework of this article is Spring MVC. The following explains what knowledge is needed to implement this function: cookies and filters

1.cookies

What are Cookies: Cookies provide a useful method for web applications to save user-related information. For example, when a user visits your site, you can use cookies to save the user's preferences or other information so that the next time the user visits your site, the application can retrieve the previously saved information.

Let’s take a look at how to save cookies and how to delete cookies

Save 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);

Delete cookies, Deletion is very simple, but it is worth noting that deleting cookies must be in the same control layer as saving cookies, otherwise the saved cookies will not be found and cannot be deleted


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

2.Filter-Filter

Filter is also called a filter. It is the most practical technology in Servlet technology. Web developers use Filter technology to , intercept all web resources managed by the web server: such as Jsp, Servlet, static image files or static html files, etc., to achieve some special functions. For example, some advanced functions such as URL-level permission access control, sensitive vocabulary filtering, and response information compression can be implemented.

Implementation method: Inherit the Filter interface and implement its doFilter method. Register the written filter class in the web.xml file and set the resources it can intercept


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

Let’s take a look at the actual application code:


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 {
  }
}

It can be seen from the code that an identification (IsAutomaticLogin) is needed to determine whether the automatic login has been performed. This identification is saved during automatic login (regardless of whether it is successful or not)

3. Based on the knowledge provided above, the following is the overall code display. If you find something wrong, you are welcome to point it out

##

@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";
  }
}

The above is the detailed content of Detailed explanation of using filters to implement customer access login function based on cookies. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn