详解Java之Spring MVC篇二

发布于:2024-11-11 ⋅ 阅读:(102) ⋅ 点赞:(0)

目录

获取Cookie/Session

理解Cookie

理解Session

Cookie和Session的区别

获取Cookie

获取Session

获取Header

获取User-Agent


获取Cookie/Session
理解Cookie

HTTP协议自身是“无状态”协议,但是在实际开发中,我们很多时候是需要知道请求之间的关联关系的。

上述图中的 "令牌" 通常就存储在 Cookie 字段中.
此时在服务器这边就需要记录"令牌"信息, 以及令牌对应的⽤⼾信息, 这个就是 Session 机制所做的⼯作.

理解Session

我们先来了解⼀下什么是会话.
会话: 对话的意思

在计算机领域, 会话是⼀个客⼾与服务器之间的不中断的请求响应. 对客⼾的每个请求,服务器能够识别出请求来⾃于同⼀个客⼾. 当⼀个未知的客⼾向Web应⽤程序发送第⼀个请求时就开始了⼀个会话.
当客⼾明确结束会话或服务器在⼀个时限内没有接受到客⼾的任何请求时,会话就结束了.
服务器同⼀时刻收到的请求是很多的. 服务器需要清楚的区分每个请求是从属于哪个⽤⼾, 也就是属于哪个会话, 就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系.

Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象.

Session的本质就是⼀个 "哈希表", 存储了⼀些键值对结构. Key 就是SessionID, Value 就是⽤⼾信息(⽤⼾信息可以根据需求灵活设计).

SessionId是由服务器⽣成的⼀个 "唯⼀性字符串", 从 Session 机制的⻆度来看, 这个唯⼀性字符串称为 "SessionId". 但是站在整个登录流程中看待, 也可以把这个唯⼀性字符串称为 "token".
上述例⼦中的令牌ID, 就可以看做是SessionId, 只不过令牌除了ID之外, 还会带⼀些其他信息, ⽐如时间, 签名等.

1. 当⽤⼾登陆的时候, 服务器在 Session 中新增⼀个新记录, 并把 sessionId返回给客⼾端. (通过HTTP 响应中的 Set-Cookie 字段返回).
2. 客⼾端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId. (通过 HTTP 请求中的Cookie 字段带上).
3. 服务器收到请求之后, 根据请求中的 sessionId在 Session 信息中获取到对应的⽤⼾信息, 再进⾏后续操作.找不到则重新创建Session, 并把SessionID返回.

Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.

Cookie和Session的区别

• Cookie 是客⼾端保存⽤⼾信息的⼀种机制. Session 是服务器端保存⽤⼾信息的⼀种机制.
• Cookie 和 Session之间主要是通过 SessionId 关联起来的, SessionId 是 Cookie 和 Session 之间的桥梁
• Cookie 和 Session 经常会在⼀起配合使⽤. 但是不是必须配合.
• 完全可以⽤ Cookie 来保存⼀些数据在客⼾端. 这些数据不⼀定是⽤⼾⾝份信息, 也不⼀定是
SessionId
• Session 中的sessionId 也不需要⾮得通过 Cookie/Set-Cookie 传递, ⽐如通过URL传递.

1. 存储位置
Cookie:存储在客户端(浏览器)上。当服务器响应一个HTTP请求时,它可以在响应头中包含一个Set-Cookie字段,浏览器会保存这个Cookie,并在后续的请求中通过Cookie请求头将Cookie发送回服务器。
Session:存储在服务器端。服务器为每个用户会话创建一个唯一的标识符(通常是Session ID),这个标识符被发送到客户端(通常是通过Cookie,但也可以通过URL重写等方式),客户端在后续的请求中携带这个标识符,服务器通过这个标识符来识别用户会话。
2. 安全性
Cookie:由于存储在客户端,因此相对容易受到攻击,如跨站脚本攻击(XSS)可以读取或修改Cookie。但是,可以通过设置HttpOnly和Secure标志来增加安全性,HttpOnly标志可以防止JavaScript访问Cookie,Secure标志则要求Cookie仅通过HTTPS发送。
Session:存储在服务器端,因此相对更安全。但是,如果Session ID被泄露(例如,通过URL重写并泄露在日志中),则可能面临会话劫持的风险。
3. 容量限制
Cookie:由于存储在客户端,其大小受到浏览器和服务器设置的限制。大多数浏览器对每个Cookie的大小和每个域名下的Cookie总数都有限制。
Session:存储在服务器端,因此其大小限制主要取决于服务器的内存和配置,通常远大于Cookie的限制。
4. 生命周期
Cookie:可以设置过期时间(Expires/Max-Age),也可以不设置(会话Cookie,浏览器关闭时失效)。
Session:通常依赖于服务器端的配置和Session的存储方式(如内存、数据库等)。如果服务器配置了Session的超时时间,则Session在达到超时时间后会被销毁。
5. 使用场景
Cookie:适用于存储少量数据,如用户偏好设置、登录状态等。由于存储在客户端,可以跨多个页面和请求持久化数据。
Session:适用于存储大量数据,如用户信息、购物车内容等。由于存储在服务器端,可以更安全地管理用户会话。

获取Cookie

首先先设置Cookie

再获取:

    @RequestMapping("/getC")
    public String getCookie(HttpServletRequest request){
        //获取参数
//        String name = request.getParameter("name");
        Cookie[] cookies = request.getCookies();
        if (cookies!=null){
            Arrays.stream(cookies).forEach(ck -> System.out.println(ck.getName()+":"+ck.getValue()));
        }
        return "获取Cookie";
    }

更为简洁的代码:

@RequestMapping("/getC2")
public String getCookie2(@CookieValue("name") String name){
    return "从Cookie中获取值, name:"+name;
}
获取Session

Session是服务器端的机制, 我们需要先存储, 才能再获取.
Session 也是基于HttpServletRequest 来存储和获取的.

设置Session

    @RequestMapping("/setSess")
    public String setSess(HttpServletRequest request){
        //从cookie中获取到了sessionID, 根据sessionID获取Session对象, 如果没有获取到, 会创建一个session对象
        HttpSession session = request.getSession();
        session.setAttribute("name", "zhangsan");
        return "设置session成功";
    }

再获取:

    @RequestMapping("/getSess")
    public String getSess(HttpServletRequest request){
        //从cookie中获取到了sessionID, 根据session获取Session对象
        HttpSession session = request.getSession();
        String name = (String)session.getAttribute("name");
        return "从session中获取name:"+name;
    }

 获取Session更为简洁的代码:

    @RequestMapping("/getSess2")
    public String getSess2(HttpSession session){
        String name = (String)session.getAttribute("name");
        return "从session中获取name:"+name;
    }

    @RequestMapping("/getSess3")
    public String getSess3(@SessionAttribute("name") String name){
        return "从session中获取name:"+name;
    }

获取Header
获取User-Agent
    @RequestMapping("/getHeader")
    public String getHeader(HttpServletRequest request){
        String userAgent = request.getHeader("User-Agent");
        return "从header中获取信息, userAgent:"+userAgent;

    }

更为简洁的代码:

    @RequestMapping("/getHeader2")
    public String getHeader2(@RequestHeader("User-Agent") String userAgent){
        return "从header中获取信息, userAgent:"+userAgent;

    }