Cookie&Session
Posted PlLI-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cookie&Session相关的知识,希望对你有一定的参考价值。
目录
2. HttpServletResponse 类中的相关方法
一. 回顾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的主要内容,如果未能解决你的问题,请参考以下文章