1、Cookie、Session、Token
1.1、会话
1.1.1、会话是什么?
在Web开发中,服务器跟踪用户信息的技术称为会话技术。
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。Web应用中的会话类似于生活中的打电话过程,它指的是一个客户端(即浏览器)与服务器之间连续发生的一系列请求与响应过程。例如,一个用户在某购物网站上的整购物过程就是一个会话。
有状态会话:如果一个用户登录过一个网站,下次再来访问该网站,我们会知道这个用户曾经来过,称之为有状态会话。
1.2、Cookie详解
1.2.1、Cookie是什么
服务器单从网络连接上无从知道客户身份。怎么办呢?
就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。所以 cookie 就是服务器发送给客户端的用来确定用户身份的 ID。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式( key - value 键值对)保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。
-
一个典型的cookie可能如下:
name=value; expires=date; path=path; domain=domain; secure; HttpOnly;
-
name
是键,value
是对应的值。 -
expires
表示Cookie的有效期。 -
path
表示Cookie适用的路径。 -
domain
表示Cookie适用的域名。 -
secure
和HttpOnly
是标志位,用于控制Cookie的安全属性。
但是在存储于浏览器中的Cookie文件里,它们通常是以更简单的键值对的形式存在:
.name = value .path = / .domain = example.com .expires = Wed, 18 Jul 2024 10:18:14 GMT
1.2.2、Cookie怎么用
-
一个网站的
cookie
是否存在上限!-
一个
cookie
只能保存一个信息; -
一个
web
站点可以给浏览器发送多个cookie
,最多存在20个cookie
; -
cookie
大小有限制4kb
; -
300个
cookie
浏览器上限。
-
-
删除cookie:
-
不设置有效期,关闭浏览器之后cookie 自动失效;
-
设置有效期时间为 0 。
-
-
编码解码:
URLEncoder.encode("myt","UTF-8"); URLDecoder.decode(cookie.getValue(),"UTF-8");
-
cookie
常用方法Cookie[] cookies = req.getCookies(); // 获得Cookie cookie.getName(); // 获得cookie中的key cookie.getValue(); // 获得cookie中的value new Cookie("lastLoginTime",System.currentTimeMillis()+""); // 新建一个cookie cookie.setMaxAge(24*60*60); // 设置cookie的有效期 resp.addCookie(cookie); // 响应给客户端一个cookie
cookie一般会保存在本地目录的appdata文件夹下
-
测试:获取用户最后一次访问的时间
public class CookieDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取用户最后一次访问的时间 // 解决中文乱码 req.setCharacterEncoding("utf-8"); // 响应乱码问题:浏览器中显示的服务器响应数据乱码 resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); // Cookie --> 服务器从客户端获取 Cookie[] cookies = req.getCookies();//这里返回数组,说明Cookie可能存在多个 // 判断Cookie是否存在 if (cookies != null) { //如果存在怎么办? out.write("你上一次访问的时间是:"); for (int i= 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; //获取cookie的名字 if ("lastLoginTime".equals(cookie.getName())){ // 获取cookie中的值 long lastLoginTime = Long.parseLong(cookie.getValue()); Date date = new Date(lastLoginTime); out.write(date.toLocaleString()); } } }else{ out.write("这是您第一次访问本站"); } // 服务器给客户端响应一个cookie Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+""); // 设置cookie有效期为1天 cookie.setMaxAge(24*60*60); resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
响应乱码问题:浏览器中显示的服务器响应数据乱码
resp.setContentType("text/html;charset=utf-8");
web.xml
配置文件
<servlet> <servlet-name>CookieDemo01</servlet-name> <servlet-class>com.myt.servlet.CookieDemo01</servlet-class> </servlet> <servlet-mapping> <servlet-name>CookieDemo01</servlet-name> <url-pattern>/c1</url-pattern> </servlet-mapping/>
1.3、Session
1.3.1、Session是什么
Session在网络应用中称为”会话控制“,是服务器为了保存用户状态而创建的一个特殊的对象。简言之,Session就是一个对象,用于存储信息。
-
Session有什么用?
举个例子,我们在浏览一个购物网站时,我们没有登录,但是我们仍然可以将商品加入购物车,并且进行查看,当我们退出浏览器再打开浏览器进行查看时,购物车中的商品仍然存在。这该怎么实现?
当然,我们可以使用cookie,但是cookie不能存放大量数据。这时候我们就需要Session了,Session是存储与服务端的特殊对象,服务器会为每一个客户端(浏览器)创建一个唯一的session。这个session是服务器共享,客户端独享。我们可以在Session存储数据,实现数据共享。
-
session的简单原理示意
1.3.2、Session常用方法
req.getSession(); // 得到请求浏览器(客户端)对应的Session。如果没有就创建新的session setAttribute(String s,Object o); // 在session中存放属性 getAttribute(String s); // 从session中得到s所对应的属性 removeAttribute(String s); // 从session中删除s对应的属性 getId(); // 得到session所对应的ID invalidate(); // 使session立即无效 setMaxInactiveInterval(int i); // 设置session的最大有效时间。注意:这个有效时间是两次访问服务器所间隔的最大时间,如果超过最大的有效时间,那么这个session就失效了。
-
在
web.xml
文件中同样可以设置session的有效时间
<!-- 设置Session的默认失效时间 --> <session-config> <!-- 设置15分钟后自动失效,以分钟为单位 --> <session-timeout>15</session-timeout> </session-config>
1.3.3、测试
获取session
import javax.servlet.ServletException; import javax.servlet.http.*; import java.io.IOException; public class SessionDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 解决中文乱码 req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); //得到Session HttpSession session = req.getSession(); // 给Session中存东西 session.setAttribute("name","mayatong"); // 获取SessionID String sessionId = session.getId(); //判断Session是不是新建 if (session.isNew()){ resp.getWriter().write("session创建成功,ID:"+sessionId); }else{ resp.getWriter().write("session已经存在服务器中了,ID:"+sessionId); } // // session创建的时候做了什么事情 // Cookie cookie = new Cookie("JSESSIONID",sessionId); // resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
注销session
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class SessionDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 解决中文乱码 req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); HttpSession session = req.getSession(); session.removeAttribute("name"); //手动注销session,session注销成功后会立刻生成一个新的sessionID session.invalidate(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
web.xml
<servlet> <servlet-name>SessionDemo01</servlet-name> <servlet-class>com.myt.servlet.SessionDemo01</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionDemo01</servlet-name> <url-pattern>/s1</url-pattern> </servlet-mapping> <servlet> <servlet-name>SessionDemo03</servlet-name> <servlet-class>com.myt.servlet.SessionDemo03</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionDemo03</servlet-name> <url-pattern>/s3</url-pattern> </servlet-mapping>
部署后启动
响应标头和请求标头中都没有携带JSESSIONID
那么这时候服务器就会创建一个JSESSIIONID,并且把这个session的JSESSIONID返回给浏览器。
我们再次访问同样的地址,这次就会携带JSESSIONID了。
我们抓包看见的响应头
我们发送的请求头
如果浏览器携带了JSESSIONID,那么浏览器在访问时就会携带。而服务器在使用session时,就会使用这个JSESSIONID的session。
然后我们访问s3使session失效
然后再次访问s1
这次,我们发现请求头和响应头都携带了JSESSIONID,这是因为session已经过期了,浏览器携带的JSESSIONID在服务器端并没有对应的session。所以服务器创建了一个新的session,并且把新的JSESSIONID返回给了游览器。
1.4、session和cookie的比较
-
cookie保存在客户端,session保存在服务端
-
cookie作用域他所表示的path中(url中要包含path),范围较小。session代表客户端和服务器的一次会话过程,web页面跳转时也可以共享数据,范围是本次会话,客户端关闭也不会消失。会持续到我们设置的session生命周期结束(默认30min)。
-
使用session需要cookie的配合。cookie用来携带JSESSIONID
-
cookie存放的数据量较小,session可以存储更多的信息。
-
cookie由于存放在客户端,相对于session更不安全
-
由于session是存放于服务器的,当有很多客户端访问时,肯定会产生大量的session,这些session会对服务器端的性能造成影响。