Cookie&Session

Posted PlLI-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cookie&Session相关的知识,希望对你有一定的参考价值。

目录

一. 回顾cookie 

二. 会话机制Session

1. cookie:标识用户的身份信息

2. cookie 和 session 的关联区别

三. 一些常用的核心方法及原理应用

1. HttpServletRequest 类中的相关方法 

2. HttpServletResponse 类中的相关方法

3. HttpSession 类中的相关方法 

4. Cookie 类中的相关方法

四. 代码案例:实现用户登录

1. 登录页面

2. LoginServlet 处理登录请求

3. IndexServlet 生成主页

4. 关注交互过程


一. 回顾cookie 

在前面的这篇文章中:(1条消息) HTTP协议&协议报文结构&请求响应数据报分析_PlLI-的博客-CSDN博客

对cookie进行了介绍。

总结来说:

1.cookie是浏览器提供的持久化存储数据的机制;

2.cookie是从服务器在 Http响应 中通过 set-cookie 字段返回给客户端的,服务器代码中由程序员决定要把什么样的信息保存到客户端中;

3.cookie会在后续再次访问服务器的时候,在Http请求的 head部分中,再把cookie带回服务器中去。(此处的作用类似于上下文, 让服务器来识别客户端此时的状态)

4.cookie是存储在浏览器(客户端)所在的硬盘中的。

在这篇文章中,再对 cookie和session之间的交互关系进行讲解,并做出案例分析。

二. 会话机制Session

服务器在同一时刻收到的请求是很多的,这也就意味着服务器是需要同一时刻去处理很多不同的请求,因此服务器就需要去区分出每个请求是属于哪个客户端的,并对其状态进行分析,然后在服务器中对每个不同的客户端进行记录。而对客户端进行记录的这个机制,就是会话机制Session。

会话本质上一个键值对,通过一个哈希表来组织的,哈希表存储了一些键值对结构,key 存储的是 sessionId,每个不同用户的sessionId是不同的,具有唯一性,value 存储的就是这个用户的信息,此处的value是可以根据需求来进行灵活设计的。

 1. 当用户登陆的时候, 服务器在 Session 中新增一个新记录,并把 sessionId 返回给客户端。 (例如通过 HTTP 响应中的 Set-Cookie 字段返回)。

 2. 客户端后续再给服务器发送请求的时候,需要在请求中带上 sessionId (例如通过 HTTP 请求中的 Cookie 字段带上)。

 3. 服务器收到请求之后, 根据请求中的 sessionId  Session 信息中获取到对应的用户信息,再进行后续操作,如果获取不到,就进行重新登陆。

 而这就涉及到了 cookie 的一个最典型的应用了。

 1. cookie:标识用户的身份信息

cookie中,可以存储 sessionId,用来标识不同用户之间的不同身份信息。

以登录功能为例进行讲解: 

在登录的时候,服务器会根据客户端的身份信息,来分配一个唯一的 身份序号 sessionId,用来标识身份信息。同时服务器会通过 hash表这样的结构,把身份序号作为key,身份信息作为value,存储起来。并通过 Http响应中 set-cookie 字段,来把 sessionId传递给用户,然后用户在后续的访问中,都会带上这个 sessionId 来发送 Http请求,以便于服务器进行识别判定。当下一次请求的时候,服务器会识别 sessionId,在对应的hash表中进行查询,如果在hash表中查到了,也就知道了用户是谁了,也就不再需要重新登录,如果没查到,那就需要进行再一次登录。

2. cookie 和 session 的关联区别

关联:也就是上述登录过程的交互过程。

区别:

1. Cookie 是客户端的存储机制;session 是服务器的存储机制; 

2. Cookie 里面可以存储各种键值对,并不只是存储 sessionId,而 session 则专门用来存储用户的身份信息;

其中Cookie也是可以单独使用的,不搭配session;例如:在实现非登录的场景下;

session 也可以不搭配 Cookie使用;例如:手机app登录访问服务器,此时服务器也需要 session,但就没有了Cookie的概念,此时 sessionId就不再需要通过 cookie或者set-cookie进行传递了。Cookie是跟浏览器强相关的;

Cookie 是属于HTTP协议中的一个部分;

session则可以和HTTP无关,在 TCP等其他地方也可以用到 session;

此处再进行一次补充:所谓的会话,是一个键值对,key是sessionId,value是一个HttpSession对象。

三. 一些常用的核心方法及原理应用

 1. HttpServletRequest 类中的相关方法 

HttpSession getSession() 在服务器中获取会话。参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null;
Cookie[] getCookies() 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象。 会自动把Cookie 中的格式解析成键值对。

注意此处的 getSession() 方法既可以用于获取服务器中的会话,也可以用于创建会话。取决于参数的值,返回会话中的value,也就是 HttpSession。

例如对于请求语句:(req 为 HttpServletRequest 的一个实例)

此处的参数为 true,此时服务器就会判定当前用户是否已经有了对应的会话了(拿着请求中 cookie 里的 sessionId 查一下哈希表) 如果 sessionId 不存在,或者没查到,就创建新会话,并插入到哈希表中。如果查到了,直接返回查到的结果。

会话的创建过程:

1. 创建新的 HttpSession 对象;

2. 构造唯一的 sessionId;

3. 把这个键值对插入哈希表;

4. 把这个 sessionId 设置到响应报文的 Set-cookie 字段中;

注意:HttpSession 对象也是一个键值对。存储这用户的身份信息。 可以通过setAttribute() 和 getAttribute() 来存取键值对,此处的键值对也是由程序员自定义的数据。

用图来说明服务器中会话是如何组织的:

2. HttpServletResponse 类中的相关方法

void addCookie(Cookie cookie) 把指定的 cookie 添加到响应中。

 Cookie cookie = new Cookie("name",""heihei);

 resp.addCookie(cookie);

从抓包结果就可以观察: 

3. HttpSession 类中的相关方法 

每个HttpSession 对象也是通过键值对的形式来存储数据的。 一个 HttpSession 对象里面包含多个键值对。我们可以往 HttpSession 中存任何我们需要的信息。

当要获取数据时,使用方法 getAttribute(String name) 来获取,返回键值对中 key为 name 的对应value 值; 

当存储数据时,使用方法 setAttribute(String name, Object value) 来进行存储,name 对应键值对中的 key,value 对应 键值对中的 value;

Object getAttribute(String name) 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null.
void setAttribute(String name, Object value) 该方法使用指定的名称绑定一个对象到该 session 会话
boolean isNew() 判定当前是否是新创建出的会话

4. Cookie 类中的相关方法

每个 Cookie 对象就是一个键值对 

String getName() 该方法返回 cookie 的名称。名称在创建后不能改变。 (这个值是 Set-Cooke 字段设置给浏览器的)
String getValue() 该方法获取与 cookie 关联的值。
void setValue(String newValue) 该方法设置与 cookie 关联的值。

四. 代码案例:实现用户登录

1. 登录页面

登录页面使用form表单来进行构造Http请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text" name="username">
        <br>
        <input type="password" name="password">
        <br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

 抓包分析:

 2. LoginServlet 处理登录请求

正常情况下,验证用户密码正不正确是从数据库进行判断,此处为了简单,将用户固定为 zhangsan或者lisi,密码为123。 

package login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet 
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (!username.equals("zhangsan") && !username.equals("lisi"))
            // 登陆失败!!
            // 重定向到 登陆页面
            System.out.println("登录失败,用户名错误!");
            resp.sendRedirect("login.html");
            return;
        
        if (!password.equals("123"))
            // 登陆失败!!
            System.out.println("登录失败,密码错误!");
            resp.sendRedirect("login.html");
            return;
        
        // 登陆成功
        // 1. 创建一个会话.
        // 参数为 true:判定当前请求是否已有对应的会话,也就是拿着请求中的 cookie 里的 sessionId 查一下哈希表,如果有,直接返回已有的,没有则创建
        HttpSession session = req.getSession(true);
        // 2. 把当前的用户名和对应值构造成键值对,保存到会话中的 HttpSession. 此处 HttpSession 又可以当成一个 map 使用.
        session.setAttribute("username",username);
        // 3. 重定向到主页
        resp.sendRedirect("index");
    

抓包分析: 

 3. IndexServlet 生成主页

package login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/index")
public class IndexServlet extends HttpServlet 
    // 通过 重定向, 浏览器发起的是 GET .
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
        // 先判定用户的登陆状态.
        // 如果用户还没登陆, 要求先登陆.
        // 已经登陆了, 则根据 会话 中的用户名, 来显示到页面上.
        
        // 这个操作不会触发会话的创建.
        // 此处参数为 false:判定当前客户端是否已有对应的会话,也就是拿着请求中的 cookie 里的 sessionId 查一下哈希表,如果有,直接返回已有的,没有则不会创建
        HttpSession session = req.getSession(false);
        if (session == null)
            // 未登录状态
            System.out.println("用户未登录!");
            resp.sendRedirect("login.html");
            return;
        
        // 已经登陆
        String username = (String)session.getAttribute("username");
        resp.setContentType("text/html;charset=utf-8");
        // 构造页面
        resp.getWriter().write("欢迎 " + username + "回来!");
    

 4. 关注交互过程

 

cookie&session

1、Cookie和Session简介与区别

Session信息是存放在server端,但session id是存放在client cookie的,当然php的session存放方法是多样化的,这样就算禁用cookie一样可以跟踪

Cookie是完全保持在客户端的如:IE firefox 当客户端禁止cookie时将不能再使用

2、Cookie的配置与应用

Setcookie(string name, string value, int expire,string path, string domain, int secure);
其中name是cookie变量名称标识,你在php中将能象使用普通变量名相同来用他引用cookie变量。value是cookie变量的初始值,expire 表示该cookie
变量的有效时间;path 为该cookie变量的相关路径;domain 表示cookie变量的网站;secure 则需在 https 的安全传输时才有效。 
    例如:SetCookie("Cookie", "cookievalue",time()+3600, "/forum", ".php100.com", 1);

3、Cookie的配置与应用

接收和处理Cookie
        PHP对Cookie的接收和处理的支持非常好,是完全自动的,跟FORM变量的原则一样,特别简单。比如设置一个名为MyCookier的Cookie,
        PHP会自动从WEB服务器接收的HTTP头里把它分析出来,并形成一个与普通变量一样的变量,名为$ myCookie,这个变量的值就是Cookie的值。
        数组同样适用。另外一个办法是引用PHP的全局变量$HTTP_COOKIE_VARS数组。
        分别举例如下:(假设这些都在以前的页面里设置过了,并且仍然有效)

        echo $MyCookie;
        echo $CookieArray[0];
        echo $_COOKIE["MyCookie"]; 
        echo $HTTP_COOKIE_VARS["MyCookie"];

4、Cookie的配置与应用

删除Cookie

要删除一个已经存在的Cookie,有两个办法:

1、SetCookie("Cookie", "");
2、SetCookie("Cookie", "value" , time()-1 / time() );

使用Cookie的限制

1、必须在HTML文件的内容输出之前设置;
2、不同的浏览器对Cookie的处理不一致,且有时会出现错误的结果。
3、限制是在客户端的。一个浏览器能创建的Cookie数量最多为30个,并且每个不能超过4KB,每个WEB站点能设置的Cookie总数不能超过20个。

5、Session的配置与应用

session_start();        //初始化session.需在文件头部

$_SESSION[name]=value;  //配置Seeeion

echo $_SESSION[name];    //使用session

isset($_SESSION[name]);   // 判断

unset($_SESSION[name]);   //删除

session_destroy();             //消耗所有session

以上是关于Cookie&Session的主要内容,如果未能解决你的问题,请参考以下文章

Session&&cookie

Cookie与Session的区别-总结很好的文章(转)

cookie&session的比较

Cookie&Session

Cookie&Session

Cookie&Session会话技术