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

Posted 9Coding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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>

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

以上是关于Spring实战 - 实现自动登录的功能的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot集成Spring Security——自动登录

17Spring实战:利用AOP实现日志监控

从片段调用 Google Play 游戏服务

Flask博客实战 - 实现登录注册功能

深入浅出Spring原理及实战「开发实战系列」SpringSecurity与JWT实现权限管控以及登录认证指南

使用Spring框架实现用户登录实例