4.7Cookie,Session和Token
目录介绍
- 1.Cookie介绍
- 1.1 什么是Cookie
- 1.2 Cookie时效性简单说明
- 1.3 Cookie使用限制
- 1.4 Android中Cookie使用
- 1.5 Android中Cookie源代码分析
- 1.6 Android中如何使用Cookie的持久化
- 1.7 如何查找浏览器Cookie
- 2.Session介绍
- 2.1 什么是Session
- 2.2 如何理解Session和什么场景使用
- 2.3 Session的作用
- 3.Token介绍
- 3.1 Token的作用
- 3.2 Token的使用场景分析
- 4.这几个比较
- 4.1 Cookie和Session的区别
- 4.2 Token和Session的区别
- 其他介绍
- 参考博客
- 版本更新
1.Cookie介绍
1.1 什么是Cookie
- Cookie 在计算机中是个存储在浏览器目录中的文本文件
- 当浏览器运行时,存储在 RAM 中发挥作用 (此种 Cookies 称作 Session Cookies),一旦用户从该网站或服务器退出,Cookie 可存储在用户本地的硬盘上 (此种 Cookies 称作 Persistent Cookies)。
1.2 Cookie时效性简单说明
- 目前有些 Cookie 是临时的,有些则是持续的。
- 临时的 Cookie 只在浏览器上保存一段规定的时间,一旦超过规定的时间,该 Cookie 就会被系统清除。
- Cookie的管理又分为持久化Cookie和非持久化Cookie。
- 非持久化Cookie存储在内存中,也就意味着,其生命周期基本和app保持一致,app关闭后,Cookie丢失。
- 而持久化Cookie则是存储在本地磁盘中,app关闭后不丢失。
1.3 Cookie使用限制
- 使用限制
- Cookie 必须在 HTML 文件的内容输出之前设置;不同的浏览器 (Netscape Navigator、Internet Explorer) 对 Cookie 的处理不一致,使用时一定要考虑;客户端用户如果设置禁止 Cookie,则 Cookie 不能建立。
- 并且在客户端,一个浏览器能创建的 Cookie 数量最多为 300 个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个。博客
- Cookie使用执行流程
- A:首先,客户端会发送一个http请求到服务器端
- B: 服务器端接受客户端请求后,发送一个http响应到客户端,这个响应头,其中就包含Set-Cookie头部
- C:在客户端发起的第二次请求(注意:如果服务器需要我们带上Cookie,我们就需要在B步骤上面拿到这个Cookie然后作为请求头一起发起第二次请求),提供给了服务器端可以用来唯一标识客户端身份的信息。这时,服务器端也就可以判断客户端是否启用了cookies。尽管,用户可能在和应用程序交互的过程中突然禁用cookies的使用,但是,这个情况基本是不太可能发生的,所以可以不加以考虑,这在实践中也被证明是对的。
1.4 Android中Cookie使用
- Android中Cookie简单介绍
- 通过OkhttpClient中的CookieJar或者拦截器去管理Cookie的。理论上,我们只需在构建单例OkhttpClient的时候,设置cookiejar或者拦截器,然后具体的操作(具体的操作也就是保存Cookie,取Cookie),Okhttp框架就会帮我们自动管理Cookie。
- 如何引用Cookie呢?
- 直接展示代码,如下所示:博客
- 具体的原理是通过HashMap集合的增查特性,就可以简单有效的帮我们管理Cookie
/** * 自定义CookieJar * @param builder */ public static void addCookie(OkHttpClient.Builder builder){ builder.cookieJar(new CookieJar() { private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>(); @Override public void saveFromResponse(HttpUrl url, List<Cookie> cookies) { cookieStore.put(url, cookies); //保存cookie //也可以使用SP保存 } @Override public List<Cookie> loadForRequest(HttpUrl url) { List<Cookie> cookies = cookieStore.get(url); //取出cookie return cookies != null ? cookies : new ArrayList<Cookie>(); } }); }
1.5 Android中Cookie源代码分析
- 具体的源代码如图所示
image
- 源代码分析说明文档
- 通过有道词典查了一下,可以看到CookieJar这个接口为HTTP cookies提供了强大的支持和相关策略。
- 作为Cookie的持久性,该接口的实现也必须要提供Cookie的存储。一种简单的实现可以将cookie存储在内存中;复杂的系统可以使用文件系统用于保存已接受的cookie的数据库。
- 将cookie存储在内存中;复杂的系统可以使用文件系统用于保存已接受的cookie的数据库。因此,我们就可以通过Map去简单的管理和使用。
- saveFromResponse方法翻译: 根据这个jar的方法,可以将cookie从一个HTTP响应保存到这里。请注意,如果响应,此方法可能被称为第二次HTTP响应,包括一个追踪。对于这个隐蔽的HTTP特性,这里的cookie只包含其追踪的cookie。简单点理解就是如果我们使用了这个方法,就会进行追踪(说白了就是客户端请求成功以后,在响应头里面去存cookie)
- loadForRequest方法翻译: 将cookie从这个方法加载到一个HTTP请求到指定的url。这个方法从网络上返回的结果可能是一个空集合。简单的实现将返回尚未过期的已接受的cookie去进行匹配。(说白了就是加载url的时候在请求头带上cookie)。
1.6 Android中如何使用Cookie的持久化
- 第一步:通过响应拦截器从response取出cookie并保存到本地,通过请求拦截器从本地取出cookie并添加到请求中
- 第二步:自定义CookieJar,在saveFromResponse()中保存cookie到本地,在loadForRequest()从本地取出cookie
- 第三步:注意在Android中,建议使用sp存储cookie,轻量级存储到本地
1.7 如何查找浏览器Cookie
- 1.我们打开浏览器,点击右上角的按钮,
- 2.然后选择更多工具下面的开发者工具选项,
- 3.接下来点击application选项,
- 4.然后我们点击左侧的Cookie选项,
- 5.接着展开cookie选项的二级内容,
- 6.最后我们选择某个地址就可以在右侧看到cookie值了
2.Session介绍
2.1 什么是Session
- Session是对于服务端来说的,客户端是没有Session一说的。
- Session是服务器在和客户端建立连接时添加客户端连接标志,最终会在服务器软件(Apache、Tomcat、JBoss)转化为一个临时Cookie发送给给客户端。
- 当客户端第一请求时服务器会检查是否携带了这个Session(临时Cookie),如果没有则会添加Session,如果有就拿出这个Session来做相关操作。
- 用浏览器打开一个网页,用到的是HTTP协议,了解计算机的应该都知道这个协议,它是无状态的,什么是无状态呢?
- 就是说这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的。但是这种无状态的的好处是快速。
- 所以就会带来一个问题就是,我希望几个请求的页面要有关联,比如:我在 www.taobao.com/login.php 里面登陆了,我在 www.taobao.com/index.php 也希望是登陆状态,但是,这是2个不同的页面,也就是2个不同的HTTP请求,这2个HTTP请求是无状态的,也就是无关联的,所以无法单纯的在index.php中读取到它在login.php中已经登陆了!
- 那咋搞呢?我不可能这2个页面我都去登陆一遍吧。
- 或者用笨方法这2个页面都去查询数据库,如果有登陆状态,就判断是登陆的了。这种查询数据库的方案虽然可行,但是每次都要去查询数据库不是个事,会造成数据库的压力。
- 所以正是这种诉求,这个时候,一个新的客户端存储数据方式出现了:cookie。cookie是把少量的信息存储在用户自己的电脑上,它在一个域名下是一个全局的,只要设置它的存储路径在域名www.a.com下,那么当用户用浏览器访问时,php就可以从这个域名的任意页面读取cookie中的信息。
- 所以就很好的解决了我在 www.a.com/login.php 页面登陆了,我也可以在 www.a.com/index.php 获取到这个登陆信息了。同时又不用反复去查询数据库。 虽然这种方案很不错,也很快速方便,但是由于cookie 是存在用户端,而且它本身存储的尺寸大小也有限,最关键是用户可以是可见的,并可以随意的修改,很不安全。
- 那如何又要安全,又可以方便的全局读取信息呢?于是,这个时候,一种新的存储会话机制:session 诞生了。
2.3 Session的作用
- Session 就是在一次会话中解决2次HTTP的请求的关联,让它们产生联系,让2两个页面都能读取到找个这个全局的session信息。
- session信息存在于服务器端,所以也就很好的解决了安全问题。博客
3.Token介绍
3.1 Token的作用
- token是用户身份的验证方式,我们通常叫它:令牌。
- 最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库。
3.2 Token的使用场景分析
- 应用场景:
- A:当用户首次登录成功(注册也是一种可以适用的场景)之后, 服务器端就会生成一个 token 值,这个值,会在服务器保存token值(保存在数据库中),再将这个token值返回给客户端.
- B:客户端拿到 token 值之后,进行本地保存。(SP存储是大家能够比较支持和易于理解操作的存储)
- C:当客户端再次发送网络请求(一般不是登录请求)的时候,就会将这个 token 值附带到参数中发送给服务器.
- D:服务器接收到客户端的请求之后,会取出token值与保存在本地(数据库)中的token值做对比
- 对比一:如果两个 token 值相同, 说明用户登录成功过!当前用户处于登录状态!
- 对比二:如果没有这个 token 值, 则说明没有登录成功.
- 对比三:如果 token 值不同: 说明原来的登录信息已经失效,让用户重新登录.
4.这几个比较
4.1 Cookie和Session的区别
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为session
其他信息如果需要保留,可以放在cookie中
4.2 Token和Session的区别
- session和 token并不矛盾,作为身份认证token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击,而session就必须靠链路层来保障通讯安全了。如上所说,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态
- App通常用restful api跟server打交道。Rest是stateless的,也就是app不需要像browser那样用cookie来保存session,因此用session token来标示自己就够了,session/state由api server的逻辑处理。如果你的后端不是stateless的rest api,那么你可能需要在app里保存session.可以在app里嵌入webkit,用一个隐藏的browser来管理cookie session.
- Session是一种HTTP存储机制,目的是为无状态的HTTP提供的持久机制。所谓Session认证只是简单的把User信息存储到Session里,因为SID的不可预测性,暂且认为是安全的。这是一种认证手段。而Token,如果指的是OAuth Token或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对App。其目的是让 某App有权利访问 某用户 的信息。这里的Token是唯一的。不可以转移到其它App上,也不可以转到其它 用户 上。转过来说Session。Session只提供一种简单的认证,即有此SID,即认为有此User的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方App。所以简单来说,如果你的用户数据可能需要和第三方共享,或者允许第三方调用API接口,用Token。如果永远只是自己的网站,自己的App,用什么就无所谓了。
- token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件;cookie就是写在客户端的一个txt文件,里面包括你登录信息之类的,这样你下次在登录某个网站,就会自动调用cookie自动登录用户名;session和cookie差不多,只是session是写在服务器端的文件,也需要在客户端写入cookie文件,但是文件里是你的浏览器编号.Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。