原文链接:blog.ouyangsihai.cn >> 一文看懂cookie和session
一、会话的概念
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
二、会话过程中要解决的一些问题
每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。
三、保存会话数据的两种技术
1、Cookie
Cookie意为"甜饼",是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
精彩内容推荐
一套java架构师学习资源,等你拿
java实战练习项目教程
你所需要的大数据视频教程
java全套学习视频教程及源码
微服务资源springboot、springcloud、docker、dubbo项目实战等倾心分享
2、Session
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
四、Cookie类的主要方法
int getMaxAge() | 返回Cookie过期之前的最大时间,以秒计算。 |
---|---|
void setMaxAge(intexpiry) | 以秒计算,设置Cookie过期时间。 |
String getName() | 返回Cookie的名字。名字和值是我们始终关心的两个部分,笔者会在后面详细介绍 getName/setName。 |
void setValue(String newValue) | Cookie创建后设置一个新的值。 |
String getValue() | 返回Cookie的值。笔者也将在后面详细介绍getValue/setValue。 |
void setDomain(String pattern) | 设置cookie中Cookie适用的域名 |
String getDomain() | 返回Cookie中Cookie适用的域名. 使用getDomain() 方法可以指示浏览器把Cookie返回给同 一域内的其他服务器,而通常Cookie只返回给与发送它的服务器名字完全相同的服务器。注意域名必须以点开始(例如.yesky.com) |
void setPath(String uri) | 指定Cookie适用的路径。 |
String getPath() | 返回Cookie适用的路径。如果不指定路径,Cookie将返回给当前页面所在目录及其子目录下 的所有页面。 |
void setSecure(boolean flag) | 指出浏览器使用的安全协议,例如HTTPS或SSL。 |
boolean getSecure() | 如果浏览器通过安全协议发送cookies将返回true值,如果浏览器使用标准协议则返回false值。 |
void setVersion(int v) | Cookie所遵从的协议版本。 |
int getVersion() | 返回Cookie所遵从的协议版本。 |
void setComment(String purpose) | 设置cookie中注释。 |
String getComment() | 返回Cookie中注释,如果没有注释的话将返回空值。 |
Cookie(String name, String value) | 实例化Cookie对象,传入cooke名称和cookie的值。 |
response接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。
五、Cookie使用
1、使用cookie记录用户上一次访问的时间
public class CookieDemo extends HttpServlet{
private static final long serialVersionUID = 5757885987685925915L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置服务器以UTF-8编码输出
resp.setCharacterEncoding("UTF-8");
//设置浏览器以UTF-8编码进行接收
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
//获取Cookie数组
Cookie[] cookie = req.getCookies();
if(cookie == null){
out.write("这是你的第一次访问!");
} else {
for (Cookie ck : cookie) {
if(ck.getName().equals("cookieName")){
//获取Cookie里面保存的数据
Long time = Long.parseLong(ck.getValue());
Date date = new Date(time);
out.write("上次访问时间:" + date.toLocaleString());
}
}
}
//创建一个cookie,cookie的名字是cookieName
Cookie cookies = new Cookie("cookieName", System.currentTimeMillis()+"");
//设置Cookie的有效期为1天,这样即使关闭了浏览器,下次再访问时,也依然可以通过cookie获取用户上一次访问的时间。
cookies.setMaxAge(24*60*60);
//将cookie对象添加到response对象中
resp.addCookie(cookies);
}
}
第一次访问时,如下所示:
再次访问:
2、删除Cookie
public class CookieDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//创建一个名字为lastAccessTime的cookie
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+"");
//将cookie的有效期设置为0,命令浏览器删除该cookie
cookie.setMaxAge(0);
req.addCookie(cookie);
}
}
3、cookie中存/取中文
public class CookieDemo2 extends HttpServlet{
private static final long serialVersionUID = 5757885987685925915L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置服务器以UTF-8编码输出
resp.setCharacterEncoding("UTF-8");
//设置浏览器以UTF-8编码进行接收
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
//创建一个cookie,cookie的名字是cookieName
//存储中文时,使用URLEncoder类里面的encode(String s, String enc)方法进行中文转码
Cookie cookies = new Cookie("cookieName", URLEncoder.encode("哎哟!不错哟", "UTF-8"));
//将cookie对象添加到response对象中
resp.addCookie(cookies);
//获取Cookie数组
Cookie[] cookie = req.getCookies();
if(cookie != null){
for (Cookie ck : cookie) {
if(ck.getName().equals("cookieName")){
//获取Cookie里面保存的数据
String text = ck.getValue();
//使用URLDecoder类里面的decode(String s, String enc)进行解码
out.write("存储的中文数据:" + URLDecoder.decode(text, "UTF-8"));
}
}
}
}
}
结果如下:
Cookie注意细节
1,一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
2,一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
3,浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
4,如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
六、Session简单介绍
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
Session和Cookie的主要区别
1,Cookie是把用户的数据写给用户的浏览器。
2,Session技术把用户的数据写到用户独占的session中。
3,Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
七、Session基础知识
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
当用户打开浏览器,访问某个网站操作session时,服务器就会在服务器的内存为该浏览器分配一个session对象,该session对象被这个浏览器独占。
这个session对象也可以看做是一个容器,session默认存在时间为30min,你可以修改。
1、Session可以用来做什么
1、网上商城中的购物车
2、保存登录用户的信息
3、将某些数据放入到Session中,供同一用户的各个页面使用
4、防止用户非法登录到某个页面。
2、Session基本使用
request.getSession() | 返回这个request绑定的session对象,如果没有,则创建一个 |
---|---|
request.getSession(boolean create) | 返回这个request绑定的session对象,如果没有,则根据create的值决定是否创建一个 |
session.setAttribute(String name,Object val) | 向session中添加属性 |
session.getAttribute(String name) | 从session中得到某个属性 |
session.removeAttribute(String name) | 从session中删除某个属性 |
session.setMaxInactiveInterval() | 设置Session的生命周期(单位秒),Session的生命周期默认是30min |
session.invalidate() | 清除所有session |
session.removeAttribute(String name) | 删除指定名称的session |
Servlet1:
public class Servlet1 extends HttpServlet {
private static final long serialVersionUID = -8236507185410764108L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session
HttpSession session = req.getSession();
//将数据存储到session中
session.setAttribute("name", "Zender");
}
}
Servlet2:
public class Servlet2 extends HttpServlet {
private static final long serialVersionUID = -8236507185410764108L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session
HttpSession session = req.getSession();
//获取name
String name = (String) session.getAttribute("name");
PrintWriter out = resp.getWriter();
out.print("name:" + name);
}
}
同一浏览器访问Servlet1,再访问Servlet2,结果如下:
不同浏览器访问Servlet1,再访问Servlet2,结果如下:
可以看到这时候name是null,也就是没有从session对象中取出值,因为360浏览器并没有运行Servlet1来创建Session对象,上面的session对象是Chrome浏览器独占的。
3、Session生命周期
Session中的属性的默认生命周期是30min,这个默认时间可以通过修改web.xml文件来修改
1,在Tomcat根目录\conf\web.xml文件中修改
30
2,如果只需要对某一个web应用设置,则只需要修改对应web应用的web.xml文件。在这个web.xml文件中添加如上的代码:
10
除了设置默认生命周期之外,最重要的是在程序中设置,调用setMaxInacttiveInterval(int interval)
,这里的interval是以秒为单位的,而且这个方法设置的是发呆时间,比如你设置的是60秒,那么在这60秒之内如果你没有操作过session,它就会自动删除,如果你操作过,不管是设置属性还是读取属性,它都会从头开始计时。
session.setMaxInactiveInterval(60);
八、Session实现原理
服务器是如何实现一个session为一个用户浏览器服务的?
1,浏览器A先访问Servlet1,这时候它创建了一个Session,ID号为110,然后Servlet1将这个ID号以Cookie的方式返回给浏览器A。
2,浏览器A继续访问Servlet2,那么这个请求会带上Cookie值: JSESSIONID=110,然后服务器根据浏览器A传递过来的ID号找到内存中的这个Session。
3,浏览器B来访问Servlet1了,它的请求并没有带上 JSESSIONID这个Cookie值,由于它也要使用Session,所以服务器会新创建一个Session,ID号为111。
4,浏览器B继续访问Servlet2,那么这个请求会带上Cookie值: JSESSIONID=111,然后服务器根据浏览器B传递过来的ID号找到内存中的这个Session。
例如:
Servlet1:
public class Servlet1 extends HttpServlet {
private static final long serialVersionUID = -8236507185410764108L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session
HttpSession session = req.getSession();
//将数据存储到session中
session.setAttribute("name", "Zender");
PrintWriter out = resp.getWriter();
out.print("create Session OK");
}
}
Servlet2:
public class Servlet2 extends HttpServlet {
private static final long serialVersionUID = -8236507185410764108L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session
HttpSession session = req.getSession();
//获取name
String name = (String) session.getAttribute("name");
PrintWriter out = resp.getWriter();
out.println("Session ID:" + session.getId());
out.print("name:" + name);
}
}
第一次访问Servlet1时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,如下图所示:
可以看到,Request Headers中并没有Cookie的信息,而Response Headers中有这么一句话:
Set-Cookie:
JSESSIONID=05A94199DDC64311563740CC2C78D656; Path=/CookieAndSession/; HttpOnly
说明这个时候服务器向客户端通过Cookie传递回了 JSESSIONID这个属性。
然后访问Servlet2,如下图所示:
可以看到Response Headers中没有出现Set-Cookie这个头,而Request Headers中带上了Cookie这个头:
Cookie:
JSESSIONID=05A94199DDC64311563740CC2C78D656
而这个头中正包含 JSESSIONID,并且它的值也就是我们之前Set-Cookie中 JSESSIONID的值。
这就证明了我们之前图解的Session的原理,也就是服务器能够为不同的浏览器区分不同的Session的机制。
九、Session的简单应用
1,用户登录时候验证验证码
Index.jsp:
表单提交