Java中Cookie和Session的那些事儿

作者:luoxn28 时间:2022-09-24 08:24:54 

Cookie和Session都是为了保持用户的访问状态,一方面为了方便业务实现,另一方面为了简化服务端的程序设计,提高访问性能。Cookie是客户端(也就是浏览器端)的技术,设置了Cookie之后,每次访问服务端,请求中都会带上Cookie;Session是服务端技术,在服务端存储用户的访问信息。

使用Cookie传递信息,随着Cookie个数增多和访问量增大,它占用的带宽会越来越大;使用Session保存信息,最大的弱点就是不容易在多台服务器之间共享。

1 Cookie

通俗地讲,当用户使用HTTP访问服务器时,服务器会将一些键值对信息返回给客户端浏览器,并且给这些数据加一些限制条件,在符合限制条件情况下用户下次访问服务器时,会带上之前设置的Cookie键值对信息。当该用户输入 URL 时,浏览器便会在本地硬盘上查找与该 URL 关联的 Cookie。如果该 Cookie 存在,浏览器便将该 Cookie 与页请求一起发送到您的站点。

Cookie 与网站关联,而不是与特定的页面关联。因此,无论用户请求站点中的哪一个页面,浏览器和服务器都将交换 Cookie 信息。用户访问不同站点时,各个站点都可能会向用户的浏览器发送一个 Cookie;浏览器会分别存储所有 Cookie。

Cookie属性项

当前Cookie有2个版本,Version 0 和 Version 1,它们有2种设置响应头标识,分别是"Set-Cookie"和"Set-Cookie2"。

Cookie 0属性值

Java中Cookie和Session的那些事儿

Cookie 1属性值

Java中Cookie和Session的那些事儿

Java中使用Cookie示例


@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
Cookie[] cookies = request.getCookies();
String name = getCoodie(cookies, "name");
if (name == null) {
response.addCookie(new Cookie("name", "luoxn28"));
}
else {
System.out.println(name);
}
out.println("hello world");
}
public static String getCoodie(Cookie[] cookies, String key) {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(key)) {
return cookie.getValue();
}
}
}
return null;
}

Java中Cookie和Session的那些事儿

使用Cookie的一些注意事项(以Java使用为例)

•所创建的Cookie的name和value不能为非ASSIC字符,如果是中文,可以通过RRLEncoder将其编码,否则会抛出java.lang.IllegalArgumentException异常。

•多出现多个name和value值时,它们实在同一个"Cookie"头中的。

•Cookies的值中可以保存除了“;”以外的标点符号。但是不能保存汉字。保存汉字会出现乱码。

Cookie的一些限制

Cookie是HTTP头中的一个字段,HTTP本身对该字段没有限制,但是Cookie最终存储在浏览器中,不同的浏览器对Cookie的存储有一些限制,如下表所示:

Java中Cookie和Session的那些事儿

Java中Cookie和Session的那些事儿

如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。

2 Session

Session解决了Cookie增多时会增加客户端与服务器的数据传输量问题,同一个客户端与服务器交互时,不需要每次都传回所有的Cookie值,而是只要传回一个ID值,这个ID是客户端第一次访问服务器时生成的,而且每个客户端是唯一的,这个ID通常是name为JSESSIONID的一个Cookie。

Session是如何基于Cookie工作的呢,可以是基于URL Path Parameter方式;也可以是基于Cookie,如果没有修改Context容器中的Cookies标识,则默认也是支持的。当浏览器不支持Cookie功能时,浏览器会将用户的SessionCookieName重写到用户请求的URL参数中,它的传递方式如/path/Servlet;name=xxx;name2=xxx2?name3=xxx3。SessionCookieName如果在web.xml中配置session-config配置项,其cookie-config下的name属性就是这个SessionCookieName的值。如果没有配置session-config配置项,默认的SessionCookieNamejiushi “JSESSIONID”。注意,与Session关联的Cookie与其他Cookie并没有什么不同。如果客户端也支持Cookie,则Tomcat仍会解析Cookie中的Session ID,并会覆盖URL中的Session ID。

Session如何工作

有了Session ID,服务器就可以创建HttpSession对象了,第一次调用request.getSession()方法,如果没有对应的HttpSession对象,则会创建一个新的,并将这个对象加入到org.apache.catalina.Manager的sessions容器中保存。Manage保存所有的session生命周期,Session过期被回收,服务器关闭,Session被序列化到磁盘。注意,一个客户端对应一个Session对象,这个对象正是保存我们创建的Session值的。

Java中Cookie和Session的那些事儿

request.getSession()方法调用的StandardSession永远都会存在,即使与这个客户端关联的Session已经过期。如果过期,则会创建一个新的,但是以前设置的Session值将会丢失。

3 Cookie与Session安全性比较

Cookie将保存的数据通过HTTP头部从客户端传到服务端,从服务端再传回到客户端,所有的数据都保存在客户端浏览器中,这些数据都是可以访问到的,甚至可以通过插件添加、修改Cookie,所有Cookie的安全性是比较差的。相比较而言,Session将数据保存在服务器端,安全性高很多,只需要Cookie传回一个Cookie ID就可以,所以Session更适合保存用户隐私和重要的数据。

分布式Session框架

在大型互联网应用中,单用Cookie和Session都是不可行的,因为如果使用Cookie可以很好地解决应用的分布式部署问题,大型互联网应用系统一个应用有上百台机器,而且有很多不同的应用系统协同工作,由于Cookie是将数据存储在用户浏览器中,用户每次访问都会讲数据带回到服务器,也就解决了同一个用户的请求在不同服务器上处理而导致的Cookie不一致问题。

Java中Cookie和Session的那些事儿

由于应用是一个集群,所以不能将Session都保存在每台服务器的内存中,如果每台服务器有几十万访问用户,服务器内存也容不下,即使容得下,也无法保证该Session同步到其他服务器中,所以共享这些Session需要将它们保存在专门的分布式缓存中,可以随时读取和写入,性能要够好满足要求,如memcache/redis或者淘宝的开源分布式框架Tair都是很好的选择。

表单重复提交问题

网站中有很多地方有重复提交表单问题,为了防止表单重复提交,就要标识用户的每一次访问请求,使得每一次访问请求对服务端来说都是唯一的,为了标识用户的每次请求,可以在用户请求的表单域增加一个隐藏表单项,其值为唯一的token,如:


<form id="form" method="post">
...
<input type=hidden name="token" value="xxx"/>
</form>

用户请求表单时生成唯一的token,并且设置到该用户的Session中,等用户提交时检测这个token是否和Session中保存的token一致,如果一致,说明没有重复提交,同时把Session中的token更新成一个新的token值;否则用户提交上来的token已经不是当前请求的合法token,提交失败。

Java中Cookie和Session的那些事儿

以上所述是小编给大家介绍的Java中Cookie和Session的那些事儿网站的支持!

来源:http://www.cnblogs.com/luoxn28/p/5894557.html

标签:session和cookie
0
投稿

猜你喜欢

  • springboot中@Async默认线程池导致OOM问题

    2022-12-19 20:07:01
  • Spring Security认证的完整流程记录

    2021-12-15 13:04:03
  • Java面向对象基础知识之封装,继承,多态和抽象

    2022-11-18 07:35:59
  • Java中equalsIgnoreCase()方法的使用

    2022-07-28 15:13:45
  • ElasticSearch查询文档基本操作实例

    2023-11-24 14:20:02
  • android图片转换器示例

    2022-02-16 14:27:01
  • SpringBoot Redis用注释实现接口限流详解

    2022-03-15 17:40:55
  • Winform启动另一个项目传值的方法

    2021-12-27 07:44:58
  • Android实现屏幕保持常亮功能

    2023-08-09 13:20:15
  • Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)

    2022-04-14 03:32:22
  • MyBatis如何进行双重foreach循环

    2022-11-24 22:54:17
  • Android中使用ZXing生成二维码(支持添加Logo图案)

    2023-12-24 21:34:58
  • Android实现给TableLayou绘制边框的方法

    2021-08-04 02:08:41
  • C#如何优雅的结束线程

    2022-07-27 19:45:27
  • Android轻松画出触摸轨迹

    2022-05-07 11:02:03
  • 使用java实现http多线程断点下载文件(一)

    2023-11-23 15:45:51
  • Spring如何解决单例bean线程不安全的问题

    2023-12-18 23:50:20
  • java实现向有序数组中插入一个元素实例

    2023-04-03 23:10:49
  • 关于Java中配置ElasticSearch集群环境账号密码的问题

    2022-10-20 09:10:18
  • 浅谈java安全编码指南之死锁dead lock

    2023-06-22 04:49:19
  • asp之家 软件编程 m.aspxhome.com