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