美文网首页
Cookie 与 Session

Cookie 与 Session

作者: 夏海峰 | 来源:发表于2018-08-25 17:08 被阅读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最好不要用来存储过大的对象。


    本节完!!!

    相关文章

      网友评论

          本文标题:Cookie 与 Session

          本文链接:https://www.haomeiwen.com/subject/xhugiftx.html