目录
1、应用
- 登录网站,今输入用户名密码登录了,第二天再打开很多情况下就直接打开了。这个时候用到的一个机制就是cookie;
- session一个场景是购物车,添加了商品之后客户端处可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息就用到了session;
2、Cookie
- 通俗讲,是访问某些网站后在本地存储的一些网站相关信息,下次访问时减少一些步骤。更准确的说法是:Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一服务器,是在客户端保持状态的方案;
- Cookie的主要内容包括:名字,值,过期时间,路径和域。使用Fiddler抓包就可以看见,比方说我们打开百度的某个网站可以看到Headers包括Cookie;
- key, value形式。过期时间可设置的,如不设,则浏览器关掉就消失了,存储在内存当中,否则就按设置的时间来存储在硬盘上的,过期后自动清除,比方说开关机关闭再打开浏览器后他都会还存在,前者称之为Session cookie 又叫 transient cookie,后者称之为Persistent cookie 又叫 permenent cookie。路径和域就是对应的域名,a网站的cookie自然不能给b用;
3、Session
- 存在服务器的一种用来存放用户数据的类HashTable结构;
- 浏览器第一次发送请求时,服务器自动生成了一HashTable和一Session ID来唯一标识这个HashTable,并将其通过响应发送到浏览器。浏览器第二次发送请求会将前一次服务器响应中的Session ID放在请求中一并发送到服务器上,服务器从请求中提取出Session ID,并和保存的所有Session ID进行对比,找到这个用户对应的HashTable;
- 一般这个值会有个时间限制,超时后毁掉这个值,默认30分钟;
- 当用户在应用程序的 Web页间跳转时,存储在 Session 对象中的变量不会丢失而是在整个用户会话中一直存在下去;
- Session的实现方式和Cookie有一定关系。建立一个连接就生成一个session id,打开几个页面就好几个了,这里就用到了Cookie,把session id存在Cookie中,每次访问的时候将Session id带过去就可以识别了;
4、区别
- 存储数据量方面:session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象;
- 一个在客户端一个在服务端。因Cookie在客户端所以可以编辑伪造,不是十分安全;
- Session过多时会消耗服务器资源,大型网站会有专门Session服务器,Cookie存在客户端没问题;
- 域的支持范围不一样,比方说a.com的Cookie在a.com下都能用,而www.a.com的Session在api.a.com下都不能用,解决这个问题的办法是JSONP或者跨域资源共享;
5、设置过期时间(Java)
5.1、Cookie
Cookie name = new Cookie("myname",u);
name.setMaxAge(14*24*3600);
response.addCookie(name);
name.setMaxAge(0);//不记录cookie
name.setMaxAge(-1);//会话级cookie,关闭浏览器失效
name.setMaxAge(60*60);//过期时间为1小时
5.2、Session
HttpSession session = request.getSession(true);
session.setMaxInactiveInterval(30*60);
Tomcat应用的web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
Tomcat服务器:tomcat-->conf--->web.xml(同上):
不设置默认为30分钟,以上设置 session 的有效时长优先级为: 代码 > 应用 > 服务器
6、session的缺点
优点:只需要一行代码就可以方便的维持用户的会话数据。这其实是个伟大的实现
缺点:
- 当mode="InProc"时,也就是默认设置时,容易丢失数据,为什么?因为网站会因为各种原因重启
- 当mode="InProc"时,Session保存的东西越多,就越占用服务器内存,对于用户在线人数较多的网站,服务器的内存压力会比较大
- 当mode="InProc"时,程序的扩展性会受到影响,原因很简单:服务器的内存不能在多台服务器间共享
- 虽然Session可以支持扩展性,也就是设置mode="SQLServer"或者mode="StateServer",但这种方式下,还是有缺点: 在每次请求时,也不管你用不用会话数据,都为你准备好,这其实是浪费资源的
- 如果你没有关闭Session,SessionStateModule就一直在工作中,尤其是全采用默认设置时,会对每个请求执行一系列的调用。浪费资源
- 并发问题,前面有解释,也有示例
- 当你使用无 Cookie 会话时,为了安全,Session默认会使用 重新生成已过期的会话标识符 的策略, 此时,如果通过使用 HTTP POST 方法发起已使用已过期会话 ID 发起的请求, 将丢失发送的所有数据。这是因为 ASP.NET 会执行重定向,以确保浏览器在 URL 中具有新的会话标识符
7、不使用session的替换方式
替代解决方法:
- 如果需要在一个页面的前后调用过程中维持一些简单的数据,可以使用<input type="hidden" />元素来保存这些数据
- 您希望在整个网站都能共享一些会话数据,就像mode="InProc"那样。此时,我们可以使用Cookie与Cache相结合做法, 自行控制会话数据的保存与加载。具体做法也简单:为请求分配置一个Key(有就忽略),然后用这个Key去访问Cache, 以完成保存与加载的逻辑。如果要使用的会话数据数量不止一个,可以自定义一个类型或者使用一个诸如Dictionary, HashTable 这样的集合来保存它们。很简单吧,基本上这种方式就是与mode="InProc"差不多了。只是没有锁定问题,因此也就没有并发问题
- 如果您想实现mode="StateServer"类似的效果,那么可以考虑使用memcached这类技术,或者自己写个简单的服务, 在内部使用一个或者多个Dictionary, HashTable来保存数据即可。这样我们可以更精确的控制读写时机。 这种方法也需要使用Cookie保存会话ID
- 如果您想实现mode="SQLServer"类似的效果,那么可以考虑使用mongodb这类技术,同样我们可以更精确的控制读写时机。 这种方法也需要使用Cookie保存会话ID
- 从前面三种替代方法来看,如果不使用Session,那么Cookie就是必需的。其实Cookie本身就是设计用来维持会话状态的。 只是它不适合保存过大的数据而已,因此,用它保存会话ID这样的数据,可以说是很恰当的。事实上,Session就是这样做的。
推荐方法:为了保持网站程序有较好的扩展性,且不需要保存过大的会话数据,那么,直接使用Cookie将是最好的选择。 由于Cookie保存在浏览器,且不安全,所以建议只保存诸如:id, key 之类的简单数据,需要其它的会话数据时再根据这些id, Key去获取。
到这里,我想我可以回答标题中的问题了:Session,其实是没有必要使用的,不用它,也能容易地实现会话数据的保存。
8、Token
- Token的引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。
- Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。