Spring实战 - 实现自动登录的功能

  • 环境: MacOS + IntelliJ IDEA 2019.3.1 (Ultimate Edition)

Cookie:存储在用户本地终端上的数据。Cookie 中每条Cookie的存储空间4k
LocalStorage:用于本地存储,解决了Cookie存储空间不足的问题,LocalStorage
中一般浏览器支持的是5M大小。LocalStorage为永久存储。
SessionStorage:当会话结束时,SessionStorage中的键值对就会被清空。
Flash Cookie:可跨浏览器

基于Spring实战 - 用户登录,实现自动登录的功能。

1、编写CookieUtils 工具类

package com.codeonline.cats.commons.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 *
 * Cookie 工具类
 *
 * @author 码出高薪
 */
public final class CookieUtils {

  protected static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);

  /**
   * 得到Cookie的值, 不编码
   *
   * @param request
   * @param cookieName
   * @return
   */
  public static String getCookieValue(HttpServletRequest request, String cookieName) {
    return getCookieValue(request, cookieName, false);
  }

  /**
   * 得到Cookie的值,
   *
   * @param request
   * @param cookieName
   * @return
   */
  public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
    Cookie[] cookieList = request.getCookies();
    if (cookieList == null || cookieName == null){
      return null;
    }
    String retValue = null;
    try {
      for (int i = 0; i < cookieList.length; i++) {
        if (cookieList[i].getName().equals(cookieName)) {
          if (isDecoder) {
            retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
          } else {
            retValue = cookieList[i].getValue();
          }
          break;
        }
      }
    } catch (UnsupportedEncodingException e) {
      logger.error("Cookie Decode Error.", e);
    }
    return retValue;
  }

  /**
   * 得到Cookie的值,
   *
   * @param request
   * @param cookieName
   * @return
   */
  public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
    Cookie[] cookieList = request.getCookies();
    if (cookieList == null || cookieName == null){
      return null;
    }
    String retValue = null;
    try {
      for (int i = 0; i < cookieList.length; i++) {
        if (cookieList[i].getName().equals(cookieName)) {
          retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
          break;
        }
      }
    } catch (UnsupportedEncodingException e) {
      logger.error("Cookie Decode Error.", e);
    }
    return retValue;
  }

  /**
   * 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response,
      String cookieName, String cookieValue) {
    setCookie(request, response, cookieName, cookieValue, -1);
  }

  /**
   * 设置Cookie的值 在指定时间内生效,但不编码
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response,
      String cookieName, String cookieValue, int cookieMaxage) {
    setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
  }

  /**
   * 设置Cookie的值 不设置生效时间,但编码
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response,
      String cookieName, String cookieValue, boolean isEncode) {
    setCookie(request, response, cookieName, cookieValue, -1, isEncode);
  }

  /**
   * 设置Cookie的值 在指定时间内生效, 编码参数
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response,
      String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
    doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
  }

  /**
   * 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response,
      String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
    doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
  }

  /**
   * 删除Cookie带cookie域名
   */
  public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,
      String cookieName) {
    doSetCookie(request, response, cookieName, "", -1, false);
  }

  /**
   * 设置Cookie的值,并使其在指定时间内生效
   *
   * @param cookieMaxage
   *            cookie生效的最大秒数
   */
  private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
      String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
    try {
      if (cookieValue == null) {
        cookieValue = "";
      } else if (isEncode) {
        cookieValue = URLEncoder.encode(cookieValue, "utf-8");
      }
      addCookieToResponse(request, response, cookieName, cookieValue, cookieMaxage);
    } catch (Exception e) {
      logger.error("Cookie Encode Error.", e);
    }
  }

  private static void addCookieToResponse(HttpServletRequest request, HttpServletResponse response,
      String cookieName, String cookieValue, int cookieMaxage) {
    Cookie cookie = new Cookie(cookieName, cookieValue);
    if (cookieMaxage > 0) {
      cookie.setMaxAge(cookieMaxage);
    }
    if (null != request)
    {
      cookie.setDomain(getDomainName(request));
    }
    cookie.setPath("/");
    response.addCookie(cookie);
  }

  /**
   * 设置Cookie的值,并使其在指定时间内生效
   *
   * @param cookieMaxage
   *            cookie生效的最大秒数
   */
  private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
    try {
      if (cookieValue == null) {
        cookieValue = "";
      } else {
        cookieValue = URLEncoder.encode(cookieValue, encodeString);
      }
      addCookieToResponse(request, response, cookieName, cookieValue, cookieMaxage);
    } catch (Exception e) {
      logger.error("Cookie Encode Error.", e);
    }
  }

  /**
   * 得到cookie的域名
   */
  private static final String getDomainName(HttpServletRequest request) {
    String domainName = null;

    String serverName = request.getRequestURL().toString();
    if (serverName == null || serverName.equals("")) {
      domainName = "";
    } else {
      serverName = serverName.toLowerCase();
      serverName = serverName.substring(7);
      final int end = serverName.indexOf("/");
      serverName = serverName.substring(0, end);
      final String[] domains = serverName.split("\\.");
      int len = domains.length;
      if (len > 3) {
        // www.xxx.com.cn
        domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
      } else if (len <= 3 && len > 1) {
        // xxx.com or xxx.cn
        domainName = domains[len - 2] + "." + domains[len - 1];
      } else {
        domainName = serverName;
      }
    }
    if (domainName != null && domainName.indexOf(":") > 0) {
      String[] ary = domainName.split("\\:");
      domainName = ary[0];
    }
    return domainName;
  }
}

2、在实体类User中增加isRemember

package com.codeonline.cats.entity;

/**
 * @author 码出高薪
 * @Desc.  User 实体类
 * @date 2020/1/12 04:45
 */

public class User {
  private String email;
  private String password;
  private Boolean isRemembers;

  public Boolean getRemembers() {
    return isRemembers;
  }

  public void setRemembers(Boolean remembers) {
    isRemembers = remembers;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  @Override
  public String toString() {
    return "User{" +
        "email='" + email + '\'' +
        ", password='" + password + '\'' +
        '}';
  }
}

3、在LoginController中增加Cookie的保存和设置功能

package com.codeonline.cats.web.controller;

import com.codeonline.cats.commons.context.SpringContext;
import com.codeonline.cats.commons.utils.CookieUtils;
import com.codeonline.cats.entity.User;
import com.codeonline.cats.service.UserServiceInterface;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;

/**
 * @author 码出高薪
 * @Desc.  登录控制
 * @date 2020/1/12 04:57
 */

@Controller
public class LoginController extends HttpServlet {

  private Logger logger = LoggerFactory.getLogger(LoginController.class);
  /**
   * 获取Spring容器中初始化bean, userService
   */
  private UserServiceInterface userServiceInterface = SpringContext.getBean("userService");

  private static final String COOKIE_NAME_USER_INFO = "userInfo";

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    String userInfo = CookieUtils.getCookieValue(req,COOKIE_NAME_USER_INFO);
    /**
     * 自动设置从cookie读取的email,password
     */
    if(!StringUtils.isBlank(userInfo)){
      String[] userInfoArray = userInfo.split(":");
      String email = userInfoArray[0];
      String password = userInfoArray[1];
      req.setAttribute("email",email);
      req.setAttribute("password",password);
      req.setAttribute("isRemembers",true);

    }
    req.getRequestDispatcher("/login.jsp").forward(req,resp);
      /**
       * 从cookie中获取email, password
        */
      CookieUtils.getCookieValue(req,COOKIE_NAME_USER_INFO);
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {

    String email = req.getParameter("email");
    String password = req.getParameter("password");

    boolean isRemembers = req.getParameter("isRemembers")==null?false:true;

    /**
     * 用户不选择 则清空COOKIE
     */
    if(!isRemembers){
      CookieUtils.deleteCookie(req,resp,COOKIE_NAME_USER_INFO);
    }

    User user = userServiceInterface.login(email,password);
    /**
     * 登录成功
     */
    if(user!=null)
    {
      if(isRemembers){
        /**
         * 用户信息存储一周
         */
        CookieUtils.setCookie(req,resp,"userInfo",
            String.format("%s:%s",email,password), 7*24*60*60);
      }
      /**
       * 重定向到首页
       */
      resp.sendRedirect("main.jsp");
    }
    /**
     * 登录失败
     */
    else{
      req.setAttribute("message","用户名或密码错误");
      logger.info("用户名或密码错误");
      req.getRequestDispatcher("login.jsp").forward(req,resp);
    }
  }
}

4、在login.jsp中接收传入的email,password

                <div class="input-group mb-2">
                    <input name="email" type="email" class="form-control" placeholder="邮箱" value=${email}>
                    <div class="input-group-append">
                        <div class="input-group-text">
                            <span class="fas fa-envelope"></span>
                        </div>
                    </div>
                </div>
                <div class="input-group mb-3">
                    <input name="password" type="password" class="form-control" placeholder="密码" value=${password}>
                    <div class="input-group-append">
                        <div class="input-group-text">
                            <span class="fas fa-lock"></span>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-8">
                        <div class="icheck-primary">
                            <input id="remember" name="isRemembers"  type="checkbox" ${isRemembers==true?"checked":""}>
                            <label for="remember">
                                下次自动登录
                            </label>
                        </div>
                    </div>

至此,实现自动登录功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341