Cookie 与 Session

2018-08-25  本文已影响31人  夏海峰

什么是会话?

客户端打开浏览器,通过 URL 地址发起 HTTP 请求,服务器接收请求并做出相应处理,再把处理结果返回至客户端,客户端接收数据并显示渲染,最后关闭浏览器。这整个过程就是一次会话。

会话的过程

会话的使用场景与基本原理

会话的使用场景:偏好记录、自动登录、浏览记录等。
会话的原理:在客户端或服务端保存用户信息数据,从而记录用户的信息和浏览行为。有两种实现会话的方式:Cookie 和 Session

Cookie 有哪些特点?

Cookie的会话数据保存在客户端;在每个站点下限制在 20 个Cookie 以内,每个 Cookie 不超过 4k。Cookie 的安全性相对较低。

Cookie 的工作流程是怎样的?Cookie 在客户端的保存是一直有效的吗?

某客户端第一次访问(登录)服务端时,服务端生成一个 Cookie 返回给客户端,客户端收到 Cookie后将其保存在客户端;之后再次与服务器发生交互时,会携带上这个 Cookie,从而实现了会话记录。我们可以使用 setMaxAge 来设置 Cookie 的有效期;默认情况下会话结束 Cookie 就失效。

Cookie 测试示例代码如下:

// TestCookie.java
public class TestCookie extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        res.setContentType("text/html;charset=UTF-8");
        RequestDispatcher dispatcher = null;
        // 获取用户登录的用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 创建两个 Cookie 对象
        Cookie userCookie = new Cookie("username", username);
        Cookie passCookie = new Cookie("password", password);
        // 设置 Cookie 过期时间
        userCookie.setMaxAge(2 * 60);   // 两分钟后过期
        passCookie.setMaxAge(2 * 60);

        // 把 Cookie 添加到响应体中云
        res.addCookie(userCookie);
        res.addCookie(passCookie);

        // 从请求对象中取出 Cookie
        Cookie[] cookies = req.getCookies();
        if (cookies != null) {      // 不是第一次访问(登录)时
            for (Cookie cookie: cookies) {
                if (cookie.getName().equals("username")) {
                    username = cookie.getValue();
                }
                if (cookie.getName().equals("password")) {
                    password = cookie.getValue();
                }
            }
        }
        try {
            PrintWriter out = res.getWriter();
            if (username.equals("admin") && password.equals("123456")) {
                out.println("<h1>admin 用户登录成功</h1>");
                out.close();
            } else {
                out.println("<h1>登录错误</h1>");
                out.close();
            }

        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}
// index.html
<form method='GET' action='/servlet-lesson/TestCookie'>
    <div>
        <span>用户名</span><input type='text' name='username' />
    </div>
    <div>
        <span>用户名</span><input type='password' name='password' />
    </div>
    <input type='submit' value='GET提交' />
</form>
// web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0">
    <display-name>Servlet</display-name>
    <servlet>
        <servlet-name>TestCookie</servlet-name>
        <servlet-class>
            cn.geekxia.TestCookie
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestCookie</servlet-name>
        <url-pattern>/TestCookie</url-pattern>
    </servlet-mapping>
</web-app>

Session 是怎么工作的?

Session的工作过程:当客户端第一次访问服务端时,服务端会生成一个唯一的 SessionId 编号,同时服务端会存储客户端的用户信息,并把 SessionId 写入到响应体的 Cookie 中;当客户端接收到响应体中的 Cookie后,会将存储在客户端,之后再次访问服务器时,都会带上这个 Cookie;之后每次请求,服务端会根据请求体中 Cookie 中的 SessionId 来读取存储在服务端的用户信息,从而识别用户并记录用户的相关行为,进一步为客户端用户提供个性化的数据。

Session的工作过程

Session 的生命周期

Session 默认有效期是 30 分钟。使用 setMaxInactiveInterval 方法可以设置 Session 的有效期,还可以使用部署描述符来设置其有效期,还可以调用 invalidate 方法来手动地让 Session 失效。(注意:使用接口方法对 Session 设置,其优先级高于部署描述符的 Session 设置。)

Session 测试示例代码如下:

// TestSession.java
public class TestSession extends HttpServlet {
    public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        res.setContentType("text/html;charset=UTF-8");
        
        // 获取用户登录的用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        
        // 创建一个 Session 对象
        HttpSession session = req.getSession();
        // 设置 Session 对象的过期时间
        session.setMaxInactiveInterval(2 * 60);
        // 手动设置 Session 过期
        // session.invalidate();
        
        // 从 Session 对象中读取用户信息。如果是第一次访问,Session 中是没有用户信息的
        String name = (String)session.getAttribute("username");
        PrintWriter out = res.getWriter();
        if (name != null) { // 再次访问时
            out.println("<h1>"+name+" 再次访问,自动登录</h1>");
            out.close();
        } else {    // 第一次访问时
            out.println("<h1>"+name+" 第一次访问</h1>");
            out.close();
        }
        // 把用户信息保存到 Session 对象中去,保存在服务端。这样的Session 是存储在服务端的内存中的。
        session.setAttribute("username", username);
        // 当客户端第一次访问时,会以 Cookie的方式向客户端写入一个名为 JSESSIONID 的 Cookie。
        // 客户端再次访问时,便可以些来读取服务端中 Session 对象中所存储的用户信息了。
    }
}
// index.html
<form method='POST' action='/servlet-lesson/TestSession'>
    <div>
        <span>用户名</span><input type='text' name='username' />
    </div>
    <div>
        <span>用户名</span><input type='password' name='passname' />
    </div>
    <input type='submit' value='POST提交' />
</form>
// web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0">
    <display-name>Servlet</display-name>
    <session-config>
        <session-timeout>2</session-timeout>
    </session-config>
    <servlet>
        <servlet-name>TestSession</servlet-name>
        <servlet-class>
            cn.geekxia.TestSession
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestSession</servlet-name>
        <url-pattern>/TestSession</url-pattern>
    </servlet-mapping>
</web-app>

上述部署描述符中,<session-config> 用于统一对 Session 进行配置,<session-timeout> 用于配置 Session 过期时间,其单位是分钟,其优先级比接口 API 对Session设置的优先级要低。

关于 Cookie 和 Session 的差异对比与小结:

前者存储在客户端,相对不安全;后者存储在服务端的内存中,相对较安全。
前者的生命周期是累加的,到时间后就失效;后者的生命周期是间隔的,即以最后一次访问时开始计时,间隔时间大于有效期时间才会失效。
前者在每个站点下最多只能有 20 个Cookie,且每个 Cookie 不能大于 4k。后者是存储在服务端的内存中的,所以 Session最好不要用来存储过大的对象。


本节完!!!
上一篇下一篇

猜你喜欢

热点阅读