session-cookie-前后端分离-跨域

前言

为什么取这个的标题?
因为这四者都有一些关联。session 的 实现 依赖于 cookie,前后端分离引起跨域问题,导致 session 失效。

1.会话跟踪技术

试想,我正在开发一个 java应用,设置权限,对有些页面只有登录的人才允许访问,我们又知道 http 请求是无状态的,不会保留客户端信息,那我们如何实现这个功能呢,既然 请求是无状态的,也就是不能保留用户的登录信息,岂不是每次访问有权限的页面都要进行一次登录?显示这是不合适 也 不合理的,所以我们需要有一种技术,可以用来保存 用户的信息,于是就出现了会话跟踪技术。

简单点说:会话跟踪技术,就是让 “http 有状态”,能记录用户相关信息等。

1,什么是会话

会话是一个终端用户(服务器)与交互系统(客户端)的通讯过程

2,什么是会话跟踪

对同一用户对服务器的连续的请求和接受响应的监视。(将用户与同一用户发出的不同的请求之间关联,为了数据共享)

3,为什么需要会话跟踪技术

服务器与客户端之间是用HTTP协议进行通信的。而HTTP协议是无状态的协议,无法储存客户的信息,即一次响应完成之后连接就断开了,下一次的请求需要重新连接。这就需要判断是否是同一用户

2.如何实现会话跟踪呢?

假如要你来实现 会话跟踪,你会怎么去实现呢?

我的大致思路是这样的:既然我们需要保存用户信息,也就是要辨别这次请求时哪个用户发过来的,然后再把 ta 对应的内容给 ta。这像不像 一个 map 结构。key 是辨别每个用户(同一个ip请求)的唯一标识,value是一个集合,用来保存信息的信息。当用户请求过来时,我们可以获取这个 唯一标识,根据 key 获取 value,取出里面的 一个 isLogin 值,判断是否为 true,就可以辨别 用户是否登录了。

其实这就是 cookie 和 session,别人早已经帮我们实现了。

3.cookie

1,什么是 cookie?

HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。

打个比方,我们去银行办理储蓄业务,第一次给你办了张银行卡,里面存放了身份证、密码、手机等个人信息。当你下次再来这个银行时,银行机器能识别你的卡,从而能够直接办理业务。

2,cookie机制
当用户第一次访问并登陆一个网站的时候,cookie的设置以及发送会经历以下4个步骤:

客户端发送一个请求到服务器 --> 服务器发送一个HttpResponse响应到客户端,其中包含Set-Cookie的头部 --> 客户端保存cookie,之后向服务器发送请求时,HttpRequest请求中会包含一个Cookie的头部 -->服务器返回响应数据

3,cookie属性项

属性项 属性项介绍
NAME=VALUE 键值对,可以设置要保存的 Key/Value,注意这里的 NAME 不能和其他属性项的名字一样
Expires 过期时间,在设置的某个时间点后该 Cookie 就会失效
Domain 生成该 Cookie 的域名,如 domain=“www.baidu.com”
Path 该 Cookie 是在当前的哪个路径下生成的,如 path=/wp-admin/
Secure 如果设置了这个属性,那么只会在 SSH 连接时才会回传该 Cookie
  • Expires

该属性用来设置Cookie的有效期。Cookie中的maxAge用来表示该属性,单位为秒。Cookie中通过getMaxAge()和setMaxAge(int maxAge)来读写该属性。maxAge有3种值,分别为正数,负数和0。

如果maxAge属性为正数,则表示该Cookie会在maxAge秒之后自动失效。浏览器会将maxAge为正数的Cookie持久化,即写到对应的Cookie文件中(每个浏览器存储的位置不一致)。无论客户关闭了浏览器还是电脑,只要还在maxAge秒之前,登录网站时该Cookie仍然有效。下面代码中的Cookie信息将永远有效。

当maxAge属性为负数,则表示该Cookie只是一个临时Cookie,不会被持久化,仅在本浏览器窗口或者本窗口打开的子窗口中有效,关闭浏览器后该Cookie立即失效。

  • Cookie的域名

Cookie是不可以跨域名的,隐私安全机制禁止网站非法获取其他网站的Cookie。

正常情况下,同一个一级域名下的两个二级域名也不能交互使用Cookie,比如test1.mcrwayfun.comtest2.mcrwayfun.com,因为二者的域名不完全相同。如果想要mcrwayfun.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数为.mcrwayfun.com,这样使用test1.mcrwayfun.comtest2.mcrwayfun.com就能访问同一个cookie

  • Cookie的路径

path 属性决定允许访问Cookie的路径。比如,设置为/表示允许所有路径都可以使用Cookie

4.session

一般译作会话,从不同层面看待session,它有着类似但不全然相同的含义。如:从web应用的用户看来,他打开浏览器访问一个电子商务网站,登录、并完成购物直到关闭浏览器,这是一个会话。而在web应用开发者看来,用户登录时我需要创建数据结构以存储用户的登录信息,这个结构也叫作session。因此在谈论session的时候要注意上下文环境。

session一般是在web应用的背景之下,我们知道web应用是基于HTTP协议的,而HTTP协议恰恰是一种无状态协议。也就是说,用户从A页面跳转到B页面会重新发送一次HTTP请求,而服务端在返回响应的时候是无法获知该用户在请求B页面之前做了什么的。

session是有状态的,而HTTP协议是无状态的。

解决HTTP协议自身无状态的方式有cookie和session。二者都能记录状态,前者是将状态数据保存在客户端,后者则是保存在服务端。

它的基本原理是服务端为每一个session维护一份会话信息数据,而客户端和服务端依靠一个全局唯一的表示来访问会话信息数据。用户访问web应用时,服务端程序决定何时创建session,创建session可以概括为三个步骤:

  1. 生成全局唯一的标识符(sessionid)
  2. 开辟数据存储空间。一般会在内存中创建响应的数据结构,但这种情况下,系统一旦停电,所有的会话数据就会丢失,如果是电子商务网站,这种事故会造成严重的后果。不过也可以写到文件里甚至存储在数据库中,这项虽然会增加I/O开销,但是session可以实现某种程度的持久化,而且更有利于session共享
  3. 将session的全局唯一标识符发送个客户端
    问题的关键就在服务端如何发送这个session的唯一标识符上。联系到HTTP协议,数据无非可以放到请求行、头域或Body里,基于此,一般来说会有两种常用的方式:利用cookie
    和URL重写。

利用 cookie 方式:
服务端只要设置set-cookie头就可以将session的标识符传送到客户端,而客户端此后的每一次请求都会带上这个标识符,服务器通过这个唯一标识,就可以分辨出客户端是谁了。由于cookie可以设置失效时间,所以一般包含session信息的cookie会设置失效时间为0,即浏览器进程有效时间。至于浏览器怎么处理这个0,每个款浏览器都有自己的方案,但差别都不会太大(一般体现在新建浏览器窗口的时候)。

URL重写:
多为URL重写,顾名思义就是重写URL。试想,在返回用户请求的页面之前,将页面所有的URL后面全部以get参数的方式加上session标识符(或者加在path info部分等等),这样用户在收到响应之后,无论点击哪个链接或提交表单,都会再带上这个session标识符,从而就实现了会话的保持。

4.1 session 原理

首先浏览器请求服务器访问web站点时,程序需要为客户端的请求创建一个session的时候,服务器首先会检查这个客户端请求是否已经包含了一个session标识、称为SESSIONID,如果已经包含了一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用,如果客户端请求不包含session id,则服务器为此客户端创建一个session并且生成一个与此session相关联的session id,sessionid 的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionid将在本次响应中返回到客户端保存,保存这个sessionid的方式就可以是cookie,这样在交互的过程中,浏览器可以自动的按照规则把这个标识发回给服务器,服务器根据这个sessionid就可以找得到对应的session,又回到了这段文字的开始。

session-cookie-前后端分离-跨域_第1张图片
session的有效期:

由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。

5. 跨域

5.1 为什么会出现跨域问题

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

同源策略的目的:

  • 保证用户的信息安全,防止恶意的网站盗取数据。如果缺少了同源策略,浏览器很容易受到xss、csrf的攻击。
  • 设置同源策略的主要目的是为了安全,如果没有同源策略,在浏览器中的cookie等其他数据可以任意读取,不同域下的DOM任意操作,ajax任意请求其他网站的隐私数据。

设想这样一个场景:一个恶意网站的页面通过iframe嵌入了银行的登陆页面(两者不同源)如果没有同源策略的限制,恶意网站上的js脚本就可以在用户登录银行的时候获取用户名和密码

(1)做一个假网站,里面用iframe嵌套一个银行网站 http://mybank.com。
(2)把iframe宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没有任何差别。
(3)这时如果用户输入账号密码,我们的主网站可以跨域访问到http://mybank.com的dom节点,就可以拿到用户的输入了,那么就完成了一次攻击。

5.2 什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

session-cookie-前后端分离-跨域_第2张图片

5.3 非同源限制

  • 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
  • 无法接触非同源网页的 DOM
  • 无法向非同源地址发送 AJAX 请求

5.4 跨域解决方法

1. 设置document.domain解决无法读取非同源网页的 Cookie问题

因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)

// 两个页面都设置
document.domain = 'test.com';

2.跨文档通信 API:window.postMessage()

调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)

它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
 
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');

调用message事件,监听对方发送的消息

// 监听 message 消息
window.addEventListener('message', function (e) {
  console.log(e.source); // e.source 发送消息的窗口
  console.log(e.origin); // e.origin 消息发向的网址
  console.log(e.data);   // e.data   发送的消息
},false);

3.JSONP

JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。

核心思想:网页通过添加一个

你可能感兴趣的:(java,session,web,java)