七天免登录 为什么不能用seesion,客户端的http请求自动携带cookei的机制(比较重要)涉及HTTP规范

  如果是七天免登录,和session肯定没关系,因为session不能持久化,主要是客户端一旦关闭,seesion就失效了///

所以必须是能持久化的,这就清晰了,要莫在的服务器保存,要摸在客户端设置

cook机制

1. 使用Cookie实现七天免登录

前端(登录页面)

在登录页面中,提供一个“记住我”选项,允许用户选择是否启用免登录功能。

jsp复制

记住我
后端(Servlet)

在登录成功后,根据用户是否勾选“记住我”,设置一个有效期为7天的Cookie。

java复制

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String account = req.getParameter("account");
    String password = req.getParameter("password");
    String remember = req.getParameter("remember");

    // 模拟用户验证
    boolean isValidUser = "admin".equals(account) && "123".equals(password);

    if (isValidUser) {
        // 如果用户勾选了“记住我”
        if ("1".equals(remember)) {
            Cookie cookie = new Cookie("auth_token", URLEncoder.encode(account + "-" + password, "utf-8"));
            cookie.setMaxAge(7 * 24 * 60 * 60); // 设置Cookie有效期为7天
            cookie.setPath("/"); // 设置Cookie路径
            resp.addCookie(cookie);
        }
        // 跳转到主页
        resp.sendRedirect("index.jsp");
    } else {
        // 跳转回登录页面
        resp.sendRedirect("login.jsp?error=true");
    }
}
自动登录逻辑

在用户访问主页时,检查Cookie是否存在并有效。

java复制

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    Cookie[] cookies = req.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if ("auth_token".equals(cookie.getName())) {
                String[] userInfo = URLDecoder.decode(cookie.getValue(), "utf-8").split("-");
                String account = userInfo[0];
                String password = userInfo[1];
                // 模拟验证用户信息
                if ("admin".equals(account) && "123".equals(password)) {
                    // 自动登录成功,跳转到主页
                    resp.sendRedirect("index.jsp");
                    return;
                }
            }
        }
    }
    // 如果没有找到有效的Cookie,跳转到登录页面
    resp.sendRedirect("login.jsp");
}

2. 使用JWT实现七天免登录

后端(生成JWT)

在用户登录成功后,生成一个有效期为7天的JWT,并将其存储在Cookie中。

java复制

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtUtil {
    private static final String SECRET_KEY = "your_jwt_secret_key";

    public static String generateToken(String subject) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        long expMillis = nowMillis + 7L * 24 * 60 * 60 * 1000; // 7天有效期
        Date exp = new Date(expMillis);

        return Jwts.builder()
                .setSubject(subject)
                .setIssuedAt(now)
                .setExpiration(exp)
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }
}

在登录成功后,将JWT存储在Cookie中。

java复制

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String account = req.getParameter("account");
    String password = req.getParameter("password");

    // 模拟用户验证
    boolean isValidUser = "admin".equals(account) && "123".equals(password);

    if (isValidUser) {
        String token = JwtUtil.generateToken(account);
        Cookie cookie = new Cookie("auth_token", token);
        cookie.setMaxAge(7 * 24 * 60 * 60); // 设置Cookie有效期为7天
        cookie.setPath("/");
        resp.addCookie(cookie);
        resp.sendRedirect("index.jsp");
    } else {
        resp.sendRedirect("login.jsp?error=true");
    }
}
验证JWT

在每次请求时,验证JWT的有效性。

java复制

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

public class JwtUtil {
    private static final String SECRET_KEY = "your_jwt_secret_key";

    public static Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }
}

在过滤器中验证JWT。

java复制

@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain filterChain) throws ServletException, IOException {
    Cookie[] cookies = req.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if ("auth_token".equals(cookie.getName())) {
                try {
                    Claims claims = JwtUtil.parseToken(cookie.getValue());
                    // 如果JWT有效,继续处理请求
                    filterChain.doFilter(req, resp);
                    return;
                } catch (Exception e) {
                    // JWT无效,跳转到登录页面
                    resp.sendRedirect("login.jsp");
                    return;
                }
            }
        }
    }
    // 如果没有找到有效的JWT,跳转到登录页面
    resp.sendRedirect("login.jsp");
}

注意事项

  1. 安全性:为了确保安全性,建议使用HTTPS协议传输数据,避免Cookie或JWT被窃取。

  2. Cookie设置:如果使用Cookie存储JWT,建议设置httpOnly属性,防止JavaScript访问Cookie,从而降低XSS攻击的风险。

  3. 定期更新:定期更新JWT或Cookie的密钥,防止被恶意攻击者破解。

HTTP请求会携带Cookie的原因主要与Cookie的设计初衷和工作原理有关。Cookie是一种存储在客户端(通常是浏览器)的轻量级数据存储机制,用于在用户与服务器之间保持会话状态。以下是详细解释:

1. Cookie的设计初衷

  • 保持会话状态:HTTP协议本身是无状态的,这意味着服务器不会自动记住用户之前的请求。每次HTTP请求都是独立的,服务器无法区分是同一个用户还是不同用户发起的请求。为了弥补这一缺陷,Cookie被设计出来,用于在客户端存储少量数据,以便在后续请求中携带这些数据,从而让服务器能够识别用户的身份或状态。

  • 个性化体验:通过Cookie,网站可以记住用户的偏好设置(如语言、主题、登录状态等),从而为用户提供个性化的体验。

2. Cookie的工作原理

  • 服务器设置Cookie:当用户第一次访问网站时,服务器可能会在响应中包含一个Set-Cookie头,告诉浏览器存储一些数据。例如:

    http复制

    Set-Cookie: session_id=1234567890; Path=/; HttpOnly

    这里,服务器告诉浏览器存储一个名为session_id的Cookie,值为1234567890,并且该Cookie适用于网站的所有路径(Path=/)。

  • 浏览器存储Cookie:浏览器接收到Set-Cookie头后,会将这些Cookie存储在本地。存储的位置和方式因浏览器而异,但通常会以键值对的形式保存。

  • 浏览器自动携带Cookie:在后续的HTTP请求中,浏览器会自动将与当前请求相关的Cookie附加到请求的Cookie头中。例如:

    http复制

    GET / HTTP/1.1
    Host: example.com
    Cookie: session_id=1234567890

    浏览器会根据Cookie的PathDomain等属性,判断哪些Cookie应该附加到当前请求中。

3. 为什么HTTP请求会自动携带Cookie?

  • 浏览器的自动管理机制:浏览器会自动管理Cookie的存储和发送。当浏览器发起HTTP请求时,它会检查本地存储的Cookie,找出与当前请求匹配的Cookie,并将它们附加到请求的Cookie头中。这个过程对用户是透明的,用户无需手动添加Cookie。

  • 符合HTTP协议规范:根据HTTP协议的规范,浏览器有责任在每次请求时携带与该请求相关的Cookie。这是为了实现会话管理、身份验证等功能,确保用户在浏览网站时能够保持一致的状态。

4. Cookie携带的条件

  • 匹配PathDomain属性:浏览器只会将与当前请求的URL匹配的Cookie发送给服务器。例如,如果Cookie的Domain属性是example.com,那么只有当请求的域名是example.com时,该Cookie才会被发送。

  • Cookie未过期:如果Cookie设置了ExpiresMax-Age属性,浏览器会检查Cookie是否已过期。如果已过期,浏览器不会发送该Cookie。

  • HttpOnly属性的Cookie:如果Cookie设置了HttpOnly属性,浏览器会阻止JavaScript访问该Cookie,但仍然会在HTTP请求中自动携带。

5. 举例说明

假设用户访问了一个网站,服务器在响应中设置了以下Cookie:

http复制

Set-Cookie: session_id=1234567890; Path=/; Max-Age=3600
Set-Cookie: theme=dark; Path=/; HttpOnly
  • 存储Cookie:浏览器会将这两个Cookie存储在本地。

  • 后续请求:当用户再次访问该网站时,浏览器会自动将这两个Cookie附加到请求中:

    http复制

    GET / HTTP/1.1
    Host: example.com
    Cookie: session_id=1234567890; theme=dark

总结

HTTP请求会携带Cookie,是因为浏览器会自动管理Cookie的存储和发送。这是为了实现会话管理、身份验证和个性化体验等功能。浏览器会根据Cookie的PathDomainExpires等属性,判断哪些Cookie应该附加到当前请求中,并在每次请求时自动将它们发送给服务器。

这种机制使得用户在浏览网站时能够保持一致的状态,而无需手动管理Cookie,同时也为开发者提供了方便的方式来实现会话管理和用户跟踪。


参考资料

  1. Mozilla Developer Network - HTTP Cookies

  2. RFC 6265 - HTTP State Management Mechanism

  3. Google Developers - Cookies Explained

  4. Stack Overflow - How do cookies work?

  5. W3Schools - HTTP Cookies

你可能感兴趣的:(java,tomcat,http)