Debug:获取自定义cookie为空的常见原因

简介: 1 场景在实现HandlerInterceptor接口的过程中,常用到HttpServletRequest的getCookies()方法,可以获取缓存的cookie数据。以下拦截器可以实现利用cookie实现自动登录基本思路:检查cookie在不在-检查cookie_username在不在-检查session中有没有用户-保持登录实现:import entity.User;import ser

1 场景

在实现HandlerInterceptor接口的过程中,常用到HttpServletRequest的getCookies()方法,可以获取缓存的cookie数据。

  • 以下拦截器可以实现利用cookie实现自动登录
  • 基本思路:检查cookie在不在-检查cookie_username在不在-检查session中有没有用户-保持登录
  • 实现:

import entity.User;
import service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Objects;


@Component
@Slf4j
public class LoginAdvice implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("拦截器生效.......");
        // 获取cookie
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            // 获取cookie的用户名
            String cookie_username = null;
            // 遍历cookie数组
            for (Cookie cookie : cookies) {
                if ("cookie_username".equals(cookie.getName())) {
                    // 获取cookie中的用户名
                    cookie_username = cookie.getValue();
                    break;
                }
            }
            // cookie_username非空
            if (cookie_username != null) {
                // 根据用户登录账号获取数据库中的用户信息
                User dbUser = userService.getUserByUserName(cookie_username);
                // 存在该用户
                if (dbUser != null) {
                    // 获取HttpSession对象
                    HttpSession session = request.getSession();
                    // session中是否存在该用户,如果为空,表示用户已经从session登出,但是cookie还在,需要做保持登录
                    User sessionUser = (User) session.getAttribute("userInfo");
                    if (sessionUser != null) {
                        // 检查sessionUser和数据库中的User是否一致
                        if (Objects.equals(sessionUser, dbUser)) {
                            // session中存在该用户,并且和数据库中的用户信息一致,通过拦截器
                            return true;
                        } else if (Objects.equals(sessionUser.getUserName(), dbUser.getUserName())) {
                            // 将用户保存到session中,实现保持登录
                            session.setAttribute("userInfo", dbUser);
                            return true;
                        }
                    } else {
                        // 将用户保存到session中,实现保持登录
                        session.setAttribute("userInfo", dbUser);
                        return true;
                    }
                }
            }
        }
        // 其他情况均作为不通过拦截器来处理
        return false;
    }
}

2 可能的原因

2.1 未设置cookie的存储路径

2.1.1 问题复现

// 新建cookie
Cookie cookie = new Cookie("cookie_username", userName);
// 有效期30天
cookie.setMaxAge(30 * 24 * 60 * 60);
// 写入cookie
httpServletResponse.addCookie(cookie)

2.1.2 原因

  • UA可能会从默认路径回传cookie
  • 上述代码未设置cookie的存储路径,可能会引起获取不到cookie的问题

2.1.2 解决方式

// 新建cookie
Cookie cookie = new Cookie("cookie_username", userName);
// 有效期30天
cookie.setMaxAge(30 * 24 * 60 * 60);
// 设定cookie写入的路径
cookie.setPath(httpServletRequest.getContextPath());
// 写入cookie
httpServletResponse.addCookie(cookie);
  •  在设置cookie之前需要设置cookie的存储路径

2.2 postman使用错误

2.2.1 问题复现

  • 使用postman发请求时,后端无法获取到cookie中的信息。
  • 发送请求的方式如下:

  • 点击send按钮发送请求。此时,cookies中的记录如下:

可以看到cookie是有记录的,User-Agent(UA)发送请求时,后端应获取到一致的结果。但实际上,以这种方式发送请求并不能让后端获取到cookie。

2.2.2 原因

cookie的工作过程: UA(通常是浏览器)收到响应报文,看到里面有 Set-Cookie,知道这是服务器给的身份标识,于是就保存起来,下次再请求的时候就自动把这个值放进 Cookie 字段里发给服务器。

上述动作是浏览器做的,因此按照2.1.1中的方式发送请求并不能使后端获取到cookie。

2.2.3 解决方式

代替浏览器做动作,手动将cookie放在请求头中。

按照上述方式向后端发送请求,就可以获取到cookie信息啦。

参考资料

HTTP协议笔记

什么是cookie

HTTP的报文结构

相关文章
|
存储 自然语言处理 Java
ResourceBundle.getBundle()来读取自定义的properties配置文件
ResourceBundle.getBundle()来读取自定义的properties配置文件
647 1
|
消息中间件 固态存储 Java
RocketMQ 消息发送system busy、broker busy原因分析与解决方案
RocketMQ 消息发送system busy、broker busy原因分析与解决方案
RocketMQ 消息发送system busy、broker busy原因分析与解决方案
|
前端开发 easyexcel Java
Java+EasyExcel实现文件导入导出,导入导出如此简单
项目中需要Excel文件的导入与导出Excel并下载,例如,导入员工信息,导出员工信息,手动输入比较繁琐,所以本篇博文教大家如何在Java中导入Excel文件与导出Excel文件
16106 3
Java+EasyExcel实现文件导入导出,导入导出如此简单
|
Java Linux 虚拟化
Docker 部署spring-boot项目(超详细 包括Docker详解、Docker常用指令整理等)
Docker 部署spring-boot项目(超详细 包括Docker详解、Docker常用指令整理等)
8295 2
|
数据库 数据库管理
【异常解决】svn报“Previous operation has not finished; run ‘cleanup‘ if it was interrupted”的错误解决方案
【异常解决】svn报“Previous operation has not finished; run ‘cleanup‘ if it was interrupted”的错误解决方案
1825 0
|
数据采集 JavaScript 前端开发
Python 爬虫实战:抓取和解析网页数据
【8月更文挑战第31天】本文将引导你通过Python编写一个简单的网络爬虫,从网页中抓取并解析数据。我们将使用requests库获取网页内容,然后利用BeautifulSoup进行解析。通过本教程,你不仅能够学习到如何自动化地从网站收集信息,还能理解数据处理的基本概念。无论你是编程新手还是希望扩展你的技术工具箱,这篇文章都将为你提供有价值的见解。
1345 1
Exception in thread "main" java.lang.IllegalArgumentException: U+6570 ('.notdef') is not available in the font Helvetica-Bold, encoding: WinAnsiEncoding 这个问题如何解决
【6月更文挑战第19天】Exception in thread "main" java.lang.IllegalArgumentException: U+6570 ('.notdef') is not available in the font Helvetica-Bold, encoding: WinAnsiEncoding 这个问题如何解决
2985 2
|
运维 监控 Java
Spring Boot中使用Actuator进行监控
Spring Boot中使用Actuator进行监控
|
前端开发 JavaScript 网络安全
request.getSession().getAttribute 获取不到值,获取到的是null
这篇文章讨论了在使用前后端分离架构时,通过AJAX请求进行会话管理时遇到的跨域问题,导致`request.getSession().getAttribute`获取到的值为null。解决办法是设置`withCredentials=true`以允许跨域请求携带cookie,确保请求凭证得以传递。
|
消息中间件 Java 中间件
RocketMQ 消息发送system busy、broker busy原因分析与解决方案
1、现象 最近收到很多RocketMQ使用者,反馈生产环境中在消息发送过程中偶尔会出现如下4个错误信息之一:1)[REJECTREQUEST]system busy, start flow control for a while2)too many requests and system thre.
2926 0

热门文章

最新文章

下一篇
开通oss服务