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的报文结构

相关文章
|
前端开发 应用服务中间件
SpringMVC 文件上传 消息 Required request part ‘file‘ is not present描述 由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者
SpringMVC 文件上传 消息 Required request part ‘file‘ is not present描述 由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者
1989 0
FtpClient.storeFile返回false解决方法
FtpClient.storeFile返回false解决方法
1615 0
|
4月前
|
存储 C#
【Azure APIM】APIM 策略语句如何读取请求头中所携带的Cookie信息并保存为变量
【Azure APIM】APIM 策略语句如何读取请求头中所携带的Cookie信息并保存为变量
|
前端开发 API Python
DRF自定义错误异常替换detail信息
因为自己写api定义了一套格式,但是django rest_framework的异常提醒又跟我的不一样, 要么是:
54 2
|
开发者
使用jsapi 调用openPageInWorkBenchForPC提示未找到该方法?
使用jsapi 调用openPageInWorkBenchForPC提示未找到该方法?
125 1
|
存储 PHP
PHP为什么需要设置session_set_cookie_params()函数来配置session的cookie参数?
PHP为什么需要设置session_set_cookie_params()函数来配置session的cookie参数?
211 0
springMvc18-cookievalue注解(显示cookie的值,默认必须有值
springMvc18-cookievalue注解(显示cookie的值,默认必须有值
75 0
springMvc18-cookievalue注解(显示cookie的值,默认必须有值
|
Python
fastapi 模式的额外信息,示例 / Cookie参数 / Header参数
fastapi 模式的额外信息,示例 / Cookie参数 / Header参数
236 0
fastapi 模式的额外信息,示例 / Cookie参数 / Header参数
|
JSON 测试技术 API
使用Wisdom RESTClient进行自动化测试,如何取消对返回的body内容的校验?对排除的JSON属性字段不做校验?
使用Wisdom RESTClient进行自动化测试,如何取消对返回的body内容的校验?对排除的JSON属性字段不做校验?
1220 0