前言

为什么取这个的标题?
因为这四者都有一些关联。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的有效期:

由于会有越来越多的用户访问服务器,因此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不同即为跨域

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请求。

核心思想:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

  1. 原生实现:
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字// 处理服务器返回回调函数的数据
<script type="text/javascript">function dosomething(res){// 处理获得的数据console.log(res.data)}
</script>
  1. Vue.js
this.$http.jsonp('http://www.domain2.com:8080/login', {params: {},jsonp: 'handleCallback'
}).then((res) => {console.log(res);
})

PS:服务端也要做相应得设置,返回 handleCallback 函数 ,例如

return HttpResponse("handleCallback("+result+")");

5.4 CORS

CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。

  1. 普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
  2. 带cookie跨域请求:前后端都需要进行设置
    【前端设置】根据xhr.withCredentials字段判断是否带有cookie
  • 原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容// 前端设置是否带cookie
xhr.withCredentials = true;xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');xhr.onreadystatechange = function() {if (xhr.readyState == 4 && xhr.status == 200) {alert(xhr.responseText);}
};
  • vue-resource
Vue.http.options.credentials = true
  • axios
axios.defaults.withCredentials = true

【服务端设置】
服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。

  • java 原生
/** 导入包:import javax.servlet.http.HttpServletResponse;* 接口参数中定义:HttpServletResponse response*/// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
response.setHeader("Access-Control-Allow-Credentials", "true"); // 提示OPTIONS预检时,后端需要设置的两个常用自定义头
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
  • springboot
  1. 第一种方式:(精细配置)在需要跨域的整个Controller或者单个方法上添加@CrossOrigin注解
  2. 第二种方式:全局配置
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE").maxAge(3600).allowCredentials(true);}
}
  1. 第三种方式:通过filter
@Component
@WebFilter(urlPatterns = "/*", filterName = "authFilter") //这里的“/*” 表示的是需要拦截的请求路径
public class PassHttpFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException { }@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletResponse httpResponse = (HttpServletResponse)servletResponse;httpResponse.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");httpResponse.setHeader("Access-Control-Allow-Credentials", "true");httpResponse.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8080");filterChain.doFilter(servletRequest, httpResponse);}@Overridepublic void destroy() { }
}

6. 前后端分离

6.1 什么是前后端分离

一般传统上的开发协作模式有两种:

  1. 一种是前端先写一个静态页面,写好后,让后端去套模板。静态页面可以本地开发,也无需考虑业务逻辑只需要实现View即可。不足是还需要后端套模板,这些前端代码后端需要浏览一遍,以免出错。
  2. 另一种协作模式是,前端直接去写模板,这样做的问题在于,前端编写过程中很依赖与后端环境,如果当后端没写完的情况下,前端几乎没法干活。

前后端分离:

  1. 首先要知道所有的程序都是一数据为基础的,没有数据的程序没有实际意义,程序的本质就是对程序的增删改查。
  2. 前后端分离就是把数据操作和显示分离出来。前端专注做数据显示,通过文字,图片或者图标等方式让数据形象直观的显示出来。后端专注做数据的操作。前端把数据发给后端,有后端对数据进行修改。
  3. 后端一般用java,c#等语言。后端来进行数据库的链接,并对数据进行操作。
  4. 后端提供接口给前端调用,来触发后端对数据的操作。

6.2 为什么前后端分离会引起的跨域问题

由于我们使用前后端分离的开发方式,那必然会导致 前端的页面代码 和 后端的代码 需要分别部署到不同的服务器上,即使是部署到同一个服务器,也会导致端口不一致,由此便产生了跨域问题,当然这并不是很难解决的事情,前面我们已经知道该如何解决跨域问题了。

6.3 前后端分离引起 session 无效

我们知道 由于前后端分离,出现了跨域问题,而由于跨域问题,又导致 session 失效。

分析一下为什么 session 会失效?

我们知道 cookie 默认是不支持跨域传递的(同一个一级域名下的两个二级域名),所以我们每一次发送请求给后端,并不能携带我们的 cookie,也就是不能携带 sessionid,没有sessionid,服务端就认为你是第一次访问,这就导致 session 失效。

当然前面也说过了,通过一些代码可以让 cookie 支持跨域。

记录的比较仓促,可能有些东西没想到,或者有错误,欢迎纠正!

session-cookie-前后端分离-跨域相关推荐

  1. pc网站调用微服务器,【微服务】前后端分离-跨域问题和解决方案

    跨域问题存在的原因 跨域问题的根本原因:因为浏览器收到同源策略的限制,当前域名的js只能读取同域下的窗口属性.什么叫做同源策略?就是不同的域名, 不同端口, 不同的协议不允许共享资源的,保障浏览器安全 ...

  2. 前后端分离跨域问题解决方案

    问题 因为最近在学习vue和springboot.用到了前后端分离.前端webpack打包运行的时候会启动nodejs的服务器占用8080端口,后端springboot自带tomcat启动占用1111 ...

  3. 【python学习笔记】关于python Flask前后端分离跨域问题

    关于python Flask前后端分离跨域问题 前后端分离过程中,前后端对接测试难免遇到跨域问题.因为是个新司机,所以在我经过一天的测试,才找到解决办法=-= 第一种方法 from functools ...

  4. Springboot整合Shiro前后端分离跨域问题

    Springboot整合Shiro前后端分离跨域问题 前言:SpringBoot整合shiro进行前后端分离开发时(前端是Vue),项目做了跨域配置,但还是前端请求会出现cros err–显示的跨域问 ...

  5. nginx处理前后端分离跨域问题

    在微服务中,通常会使用前后端分离的方式进行开发和部署.由于前后端分开部署,属于不同的"资源",因此前端调用后端API时可能会出现跨域问题,Cross-Origin Resource ...

  6. cors 前后端分离跨域问题_前后端分离之CORS跨域访问踩坑总结

    前言 前后端分离的开发模式越来越流行,目前绝大多数的公司与项目都采取这种方式来开发,它的好处是前端可以只专注于页面实现,而后端则主要负责接口开发,前后端分工明确,彼此职责分离,不再高度耦合,但是由于这 ...

  7. 前后端分离跨域问题Access to XMLHttpRequest at ‘http://localhos...has been blocked by CORS policy: No ‘Access-

    完整报错如下: Access to XMLHttpRequest at 'http://localhost:8081/login' from origin 'http://localhost:8084 ...

  8. nginx配置反向代理解决前后端分离跨域问题

    2019独角兽企业重金招聘Python工程师标准>>> 摘自<AngularJS深度剖析与最佳实践>P132 nginx配置文件如下: server {listen 80 ...

  9. 前后端分离 跨域问题解决

    跨域的实现原理 http 跨域请求后端服务的时候会在请求头中带上如下信息 Origin: http://api.jijs.com 后端服务器需要在http的响应头中添加以下响应头 Access-Con ...

  10. cors 前后端分离跨域问题_SpringBoot 实现前后端分离的跨域访问(CORS)

    序言:跨域资源共享向来都是热门的需求,使用CORS可以帮助我们快速实现跨域访问,只需在服务端进行授权即可,无需在前端添加额外设置,比传统的JSONP跨域更安全和便捷. 一.基本介绍 简单来说,CORS ...

最新文章

  1. 安卓高手之路之PackageManagerservice(二)
  2. 通过案例学调优之--Oracle Cluster Table
  3. 记录一下Memcached的用法:
  4. 搭建samba文件共享服务
  5. flash背景透明、置底、禁止放大 右键菜单
  6. 如何快速搭建一个免费的,无限流量的Blog
  7. Python爬虫实现:三连文章参与抽奖
  8. python无所不能_python-列表
  9. 数据结构中三表合一的实现
  10. 【实用工具】GLIBC降级
  11. Sentinel 简介与API订阅发布
  12. python searchsorted_Python 二分查找与 bisect 模块
  13. atmega328p引脚图_【ATMEGA328P-PU PDF数据手册】_中文资料_引脚图及功能_(爱特美尔 ATMEL)-采芯网...
  14. 教你如何用PS制作iOS端APP应用图标AppIcon.appiconset
  15. 河南省公安机关户政服务管理工作规范(试行)
  16. java水电费收费系统_java水电费管理系统
  17. wireshark密码嗅探侵入后台管理系统
  18. 丁磊:求快是创业者的思维误区,过于强调时间窗口也是一个伪命题
  19. 什么是研究报告,研究报告分为那些部分
  20. Linux下Makefile的automake生成全攻略(转)

热门文章

  1. linux 中ps -ef | grep java命令
  2. 牛笔了!字节跳动大佬整理:CSS 核心知识(万字长文,值得收藏!)
  3. 在Linux使用脚本实现TC控制少数人的下载带宽,如果是网管,正好用得着。
  4. devops_如何进入DevOps
  5. 安装并使用百度地图【vue】
  6. leetcode 1178.猜字谜
  7. File “C:\Users\N506\Anaconda3\lib\urllib\request.py“, line 1319, in do_open raise URLError(err
  8. 国外python经典书籍_2019学习Python最值得看的七本书
  9. 滦平一中2021年高考成绩查询,滦平县第一中学
  10. JAVA 找不到这个方法