当前位置: 移动技术网 > IT编程>开发语言>.net > 基于Cookie使用过滤器实现客户每次访问只登录一次

基于Cookie使用过滤器实现客户每次访问只登录一次

2017年12月08日  | 移动技术网IT编程  | 我要评论

广州铁一中学,龙博小说网,方小听

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

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

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

1.cookies

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

我们看一下是如何保存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.filter-过滤器

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

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

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

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

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使用过滤器实现客户每次访问只登录一次,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网