如何跨域请求携带 cookie ?
前言
最近在参加面试找工作,陆陆续续的面了两三家。其中面试官问到了一个问题:如何解决跨域问题?我巴巴拉拉的一顿说,大概了说了四种方法,然后面试官紧接着又问:那跨域请求怎么携带cookie
呢?(常规的面试套路,一般都会顺着你的回答往深了问)由于之前的项目都是同源的,不牵涉跨域访问,所以一时没有回答出来,后来研究了下,所以有了这篇文章。
阅读本文,你将学到:
1.学会`withCredentials`属性;
2.学会`axios`配置`withCredentials`;
3.学会设置`Access-Control-Allow-Origin`属性;
4.学会设置`Access-Control-Allow-Credentials`属性;
5.学会解决跨域请求携带源站cookie的问题;
一. 搭建一个跨域请求的环境
思路:
使用
express
搭建第一个服务A
(http://localhost:8000
),运行在8000
端口上;A
服务托管index.html
(用于在前端页面发送网络请求)文件;在
A
服务中写一个处理请求的路由,加载index.html
页面时,种下cookie
(这里种cookie
为了在请求B
服务时携带上);使用
express
搭建第二个服务B
(http://localhost:8003
),运行在8003
端口上;在
A
服务托管的index.html
页面去请求B
服务,然后把cookie
传过去;
先看下代码结构,相对比较的简单:
A
服务的代码:
// src/app1.js
const express = require("express");
const app = express();// `index.html` 加载时会请求login接口
// 设置`cookie`
app.get("/login", (req, res) => {res.cookie("user", "jay", { maxAge: 2000000, httpOnly: true });res.json({ code: 0, message: "登录成功" });
});// 此接口是检测`cookie`是否设置成功,如果设置成功的话,浏览器会自动携带上`cookie`
app.get("/user", (req, res) => {// req.headers.cookie: user=jayconst user = req.headers.cookie.split("=")[1];res.json({ code: 0, user });
});// 托管`index.html`页面
// 这样的话在`index.html`中发起的请求,默认的源就是`http://localhost:8000`
// 然后再去请求`http://localhost:8003`就会出现跨域了
app.use("/static", express.static("public"));app.listen("8000", () => {console.log("app1 running at port 8000");
});
index.html
的代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><h2>this is index.html at port 8000</h2><button id="button">发送同源请求</button><button id="cross-button">发送跨域请求</button><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>const button = document.querySelector("#button");const crossButton = document.querySelector("#cross-button");axios.get("http://localhost:8000/login", {}).then((res) => {console.log(res);});// 发送同域请求button.onclick = function () {axios.get("http://localhost:8000/user", {}).then((res) => {console.log(res);});};// 发送跨域请求crossButton.onclick = function () {axios({method: "get",url: "http://localhost:8003/anotherService",}).then((res) => {console.log(res);});};</script></body>
</html>
B
服务的代码:
// src/app2.js
const express = require("express");
const app = express();// 定义一个接口,index.html页面请求这个接口就是跨域(因为端口不同)
app.get("/anotherService", (req, res) => {res.json({ code: 0, msg: "这是8003端口返回的" });
});app.listen("8003", () => {console.log("app2 running at port 8003");
});
这个时候环境基本就搭建好了。
二、解决跨域携带cookie
问题
首先我们先在A
服务的index.html
页面中得到一个cookie
,运行A
服务:
npm install express -D
node src/app1.js
然后打开http://localhost:8000/static/index.html
: 没有问题的话,页面长这样:
这个时候F12
打开控制台:可以看到发送了一个login
请求,并且设置了cookie,也可以选择浏览器控制台的Application
页签,选中cookie
,可以看到cookie
的信息:
然后我们点击页面上的发送同源请求按钮,可以看到发送了一个user请求,并且已经携带上了cookie:
接下来刺激的画面来了,我们点击 发送跨域请求 按钮,出现了跨域请求的报错:
重点:接下来开始解决跨域携带cookie问题:
1. 在前端请求的时候设置request对象的属性withCredentials为true;
什么是withCredentials
?
XMLHttpRequest.withCredentials 属性是一个Boolean
类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control
)请求。在同一个站点下使用withCredentials属性是无效的。
如果在发送来自其他域的XMLHttpRequest请求之前,未设置withCredentials
为true,那么就不能为它自己的域设置cookie值。而通过设置withCredentials
为true获得的第三方cookies,将会依旧享受同源策略,因此不能被通过document.cookie或者从头部相应请求的脚本等访问。
// 修改跨域请求的代码
crossButton.onclick = function () {axios({withCredentials: true, // ++ 新增method: "get",url: "http://localhost:8003/anotherService",}).then((res) => {console.log(res);});
};
这个时候再去发送一个跨域请求,你会发现依旧报错,但是我们仔细看下报错,意思是需要设置header的Access-Control-Allow-Origin
属性:
2. 在服务端设置Access-Control-Allow-Origin
我们修改B
(app2.js)服务的代码:
// 在所有路由前增加,可以拦截所有请求
app.all("*", (req, res, next) => {res.header("Access-Control-Allow-Origin", "http://localhost:8000");next();
});
修改完之后再次发送一个跨域请求,你会发现,又报错了(接近崩溃),但是跟之前报的错不一样了,意思大概就是Access-Control-Allow-Credentials
这个属性应该设置为true
,但是显示得到的是个''
:
3. 在服务端设置Access-Control-Allow-Credentials
再次修改B服务的代码(每次修改后需要重新运行):
// 在所有路由前增加,可以拦截所有请求
app.all("*", (req, res, next) => {res.header("Access-Control-Allow-Origin", "http://localhost:8000");res.header("Access-Control-Allow-Credentials", "true"); // ++ 新增next();
});
再发送一个跨域请求:
可以看到,这个跨域请求已经请求成功并且返回数据了!而且也携带了A
服务的cookie
,这个时候已经大功告成了。
三、总结
前端请求时在
request
对象中配置"withCredentials": true
;服务端在
response
的header
中配置"Access-Control-Allow-Origin", "http://xxx:${port}"
;服务端在
response
的header
中配置"Access-Control-Allow-Credentials", "true"
如果看完这篇文章能够帮助到你,请给个赞哦~
作者:Ethan01
https://juejin.cn/post/7066420545327218725
如何跨域请求携带 cookie ?相关推荐
- 跨域请求携带cookie
默认情况下是跨域是不会携带cookie的,例如:a.com 网站请求 b.com 的接口,这个时候不会把a.com这个域名下的 cookie 携带上.如果需要携带,则需要做一下配置 前端配置 XMLH ...
- ajax跨域请求传递Cookie问题
问题描述 前后端完全分离的项目,前端使用Vue + axios,后端使用SpringMVC,容器为Tomcat. 使用CORS协议解决跨域访问数据限制的问题,但是发现客户端的Ajax请求不会自动带上服 ...
- 跨域请求传递Cookie
通过CORS跨域时,浏览器不会自动带上cookie.想要传递cookie,需要客户端与服务端共同设置. 服务端需要设置 Access-Control-Allow-Origin 该字段表明服务端接收哪些 ...
- java 跨域 cookie_跨域请求传递Cookie问题
问题描述 前后端完全分离的项目,前端使用Vue + axios,后端使用SpringMVC,容器为Tomcat. 使用CORS协议解决跨域访问数据限制的问题,但是发现客户端的Ajax请求不会自动带上服 ...
- angularjs ajax header,angularJs/ajax跨域请求携带cookies
前后端分离时候,当前端测试不在同一个域时候,前端使用ajax请求时,ajax默认不会将cookies保存,而且也不会发送cookie到服务端, 此时在请求方法中加入粗体部分即可,当然存取cookies ...
- 详细记录如何在跨域请求中携带cookie
1. 搭建环境 1.生成工程文件 npm init 2.安装 express npm i express --save 3.新增app1.js,开启服务器1 端口:3001 const express ...
- 面试官问:跨域请求如何携带cookie?
大家好,我是若川.持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列 ...
- 简单跨域请求和带预检的跨域请求
受浏览器的同源策略限制,JavaSript只能请求本域内的资源.跨域资源共享(Cross-Origin Resource Sharing, CORS)是为解决Ajax技术难实现跨域问题而提出的一个规范 ...
- 前端cookie 放到请求头_ajax请求携带cookie和自定义请求头header(跨域和同域)
错误: 1.ajax请求时是不会自动带上cookie的,要是想让他带上的话,必须设置withCredential为true. 正确: 1.ajax同域请求下,ajax会自动带上同源的cookie: 2 ...
最新文章
- 计算机学具制作,一种具有防护功能的计算机编程学具的制作方法
- Highcharts Pie 饼图提示标签IE下重叠解决方法,及json数据绑定方法
- 神策数据与 UCloud 达成战略合作,开启高效企业服务新模式
- 快速排序的C++实现(利用二分分治法)
- uva 10723 Cyborg Genes
- Oracle版本号的含义
- 苹果账号:个人,公司,企业,教育,
- 白盒测试之语句覆盖案例
- linux安装后root密码错误,linux新安装后root密码设置
- Mac OS X 通过命令行修改ip地址
- html中opacity的使用
- 梦幻西游这么火, Python也不甘示弱, Python写游戏辅助软件!
- 【JAVA操作系统——可变式分区分配】首次适应算法
- python 逐行调试工具_常用的 Python 调试工具,Python开发必读-乾颐堂
- 学计算机主修,大学计算机专业自我介绍(精选5篇)
- 苹果iPhone5 16G长沙九方现货售8199元
- mysql的mtr是指什么_关于innodb mtr模块
- thymeleaf双重循环_thymeleaf实现th:each双重多重嵌套功能
- python PDF文档
- 演讲比赛流程管理系统(C++)