面试官问:跨域请求如何携带cookie?

2023-05-16

大家好,我是若‍川。持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列

本文来自经作者 @Ethan01 授权转载
原标题:面试题 -- 跨域请求如何携带cookie?
原链接:https://juejin.cn/post/7066420545327218725

前言

最近在参加面试找工作,陆陆续续的面了两三家。其中面试官问到了一个问题:如何解决跨域问题?我巴巴拉拉的一顿说,大概了说了四种方法,然后面试官紧接着又问:那跨域请求怎么携带cookie呢?(常规的面试套路,一般都会顺着你的回答往深了问)由于之前的项目都是同源的,不牵涉跨域访问,所以一时没有回答出来,后来研究了下,所以有了这篇文章。

阅读本文,你将学到:

1.学会`withCredentials`属性;
2.学会`axios`配置`withCredentials`;
3.学会设置`Access-Control-Allow-Origin`属性;
4.学会设置`Access-Control-Allow-Credentials`属性;
5.学会解决跨域请求携带源站cookie的问题;

一. 搭建一个跨域请求的环境

思路:

  1. 使用express搭建第一个服务A(http://localhost:8000),运行在8000端口上;

  2. A服务托管index.html(用于在前端页面发送网络请求)文件;

  3. A服务中写一个处理请求的路由,加载index.html页面时,种下cookie(这里种cookie为了在请求B服务时携带上);

  4. 使用express搭建第二个服务B(http://localhost:8003),运行在8003端口上;

  5. A服务托管的index.html页面去请求B服务,然后把cookie传过去;

先看下代码结构,相对比较的简单:

b6fdd7f0bffbbbce261ec65d112a6a8f.png
image.png

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=jay
  const 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: 没有问题的话,页面长这样:

077a96c00b1d19a71ea33c721b2d9f8e.png
image.png

这个时候F12打开控制台:可以看到发送了一个login请求,并且设置了 cookie,也可以选择浏览器控制台的Application页签,选中cookie,可以看到cookie的信息:

964a9e22f4575585b81fdde019e66133.png
image.png
b03fc6fd2d152c250458cafb9c581f91.png
image.png

然后我们点击页面上的发送同源请求按钮,可以看到发送了一个 user 请求,并且已经携带上了 cookie:

a61edf597df1057b1e50bc41a6e249d2.png
image.png

接下来刺激的画面来了,我们点击 发送跨域请求 按钮,出现了跨域请求的报错:

23cb923f9d231b4db1d464b69c53ce68.png
image.png

重点:接下来开始解决跨域携带 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属性:

79003ce28b9b2f5a91ba6bdd64b81b0e.png
image.png

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,但是显示得到的是个''

da1b0b487c2786d083b88b5ec4c7ebb9.png
image.png

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();
});

再发送一个跨域请求:

33dd0426ec73c87cdacfe1f9d226d18b.png
image.png
33b54ce54a4e05f3b59e8f8ac9436bc3.png
image.png

可以看到,这个跨域请求已经请求成功并且返回数据了!而且也携带了A服务的cookie,这个时候已经大功告成了。

三、总结

  1. 前端请求时在request对象中配置"withCredentials": true

  2. 服务端在responseheader中配置"Access-Control-Allow-Origin", "http://xxx:${port}";

  3. 服务端在responseheader中配置"Access-Control-Allow-Credentials", "true"

如果看完这篇文章能够帮助到你,请给个赞哦~

0806c701afd6b050f071036f6eeb322f.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结。
同时,最近组织了源码共读活动,帮助3000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

44a6522d13085043d4b504b63b9b5f62.png

识别方二维码加我微信、拉你进源码共读

今日话题

略。分享、收藏、点赞、在看我的文章就是对我最大的支持~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试官问:跨域请求如何携带cookie? 的相关文章

  • 使用 Chrome 获取 Cookie 的数据

    Chrome 浏览器自带的开发功能相当强大 xff0c 这里只使用它的抓包功能 一 在浏览器中打开目标网站并登录 xff0c 进入目标页面 二 在 Chrome 浏览器下方的开发工具中单击 Network 标签页 按 F5 键 xff0c
  • 「VScode」在vscode中通过cookie登录leetcode

    前言 我是用中国版的leetcode xff0c 但是不知道为什么用密码登录总是失败 xff0c 最后用cookie登录上的 简单记录一下 xff0c 方便大家查看 基础设置 扩展设置 在设置中找到 endpoint 选择 leetcode
  • Cookie,sessionstorage,localstorage,Token ,JWT,session的区别

    1 cookie HTML4开始使用 xff0c 存储在客户端保存数据 xff0c 不可跨域 cookie的数据每次都会发给服务器端 不设置有效期就是存储在内存 xff0c 会话级别的存储 xff1b 设置了有效期就是存储在硬盘里 xff0
  • [JavaScript]Cookie详解(转)

    cookie概述 假如利用一个不变的框架来存储购物栏数据 xff0c 而商品显示页面是不断变化的 xff0c 尽管这样能达到一个模拟全局变量的功能 xff0c 但并不严谨 例如在导航框架页面内右击 xff0c 单击快捷菜单中的 刷新 命令
  • 权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token

    1 认证 Authentication 和授权 Authorization 的区别是什么 xff1f 这是一个绝大多数人都会混淆的问题 首先先从读音上来认识这两个名词 xff0c 很多人都会把它俩的读音搞混 xff0c 所以我建议你先先去查
  • qt 获取部分的cookie信息 如何把获取的cookie转换为QString类型 正则表达式

    qt 获取部分的cookie信息 需要解决的 1 如何把获取的cookie转换为QString类型 2 正则表达式从一堆cookie中匹配出需要的那部分cookie信息 例子 我要从以下一堆cookie信息中获取token QNetwork
  • Cookie实现自动登录案例实现

    大家好 我是一名入门的菜鸟 如果你不经意间翻开了我的文章 谢谢您 您的支持是我前进的动力 让我们一起加油 由于不是名牌大学 只是一个普普通通的专科生 所以 我想通过自己的努力来获得我想要的 我不会放弃我的梦想 我也曾幻想着我成功的时候在朋友
  • 你知道pinia和vuex的区别吗?

    Pinia和Vuex是两个不同的状态管理库 它们在设计和使用方式上有一些区别 1 Vue 版本兼容性 Pinia是为Vue 3设计的状态管理库 而Vuex是Vue 2的官方状态管理库 因此 如果您正在使用Vue 3 Pinia是一个更适合的
  • 【H5】Cookie、Session、Token、JWT区别及使用方法

    Token 和 Session 的区别 Session 是一种记录服务器和客户端会话状态的机制 使服务端有状态化 可以记录会话信息 而 Token 是令牌 访问资源接口 API 时所需要的资源凭证 Token 使服务端无状态化 不会存储会话
  • webdriver之获取cookie 转化成字典或者string的方法

    转字典 for i in cookieJs cookie server setdefault i get name i get value print cookie server 转string cookie item name item
  • Servlet配置、会话管理——Servlet【总结】

    Servlet配置 初始化参数 Servlet除了可以从请求信息中获取信息外 还可以从配置文件中获取配置参数信息 配置文件中的参数信息与具体的请求无关 而是Servlet初始化时调用的 如此可以避免硬编码信息 提高Servlet的可移植性
  • Cookie伪造

    解题 创建了一个user用户登陆之后发现 抓包看一下 登录 注册完一个账号 sgx密码 sgx 随便注册 第一次登录时发现它会在服务器中存下一个cookie值并且前缀都是351e766803 把后面的md5解密下发现是sgx和limited
  • COOKIE与SESSION的区别

    Web基础 COOKIE与SESSION的区别 一 COOKIE 1 COOKIE是什么 cookie可以理解是服务器暂存在客户端的文本信息 txt文件 2 COOKIE从哪来 cookie从服务端来 它是由服务端生成的 客户端可以清除co
  • 爬虫项目七:Python对唯品会商品数据、评论数据的爬取

    文章目录 前言 一 商品数据 1 分析页面 2 分析url 3 解析数据 二 评论数据 1 抓包 2 分析url 3 获取数据 三 总结 前言 用Python爬取唯品会商品数据 评论数据 提示 以下是本篇文章正文内容 下面案例可供参考 一
  • cookie设置为关闭浏览器后清除,打开后cookie还是没有清除

    今天踩了几个cookie的坑 花了我2小时 问题是这样的 我给aaa域名下的a html页面设置了一条很简单的cookie document cookie name abc 这样设置后默认为关闭浏览器后清除该cookie 可是关闭后打开co
  • 做web开发,怎么能不懂cookie、session和token呢?

    如果把人体比作一个web系统的话 cookie session和token就好像人体的经络和血管一样 而web系统中的数据 就好像人体的血液一样 血液依靠着血管在人体内流动 就如数据根据cookie和session机制在web系统中流动一样
  • 转:Cookie详解

    没怎么坐过客户端相关的工作 所以写爬虫的时候 很多概念都很模糊 学习起来很困难 现在想攻坚一下 所以找了一下cookies相关的内容 HTTP cookies 通常又称作 cookies 早期Web开发面临的最大问题之一是如何管理状态 服务
  • Asp.net 之Cookie简单介绍与使用

    什么是Cookie Cookie 有时也用其复数形式Cookies 指某些网站为了辨别用户身份 进行session跟踪而储存在用户本地终端上的数据 通常经过加密 所以查看浏览器保存到本地的Cookie时 一般都是一个文本文件这些文件通常是以
  • 运用Cookie技术,统计访问次数以及上次访问时间。

    package servlet import java io IOException import java io PrintWriter import java text SimpleDateFormat import java util
  • 转:Chrome浏览器查看网站登录 Cookie 信息的方法

    当我们使用自动签到等程序的时候一般都要用到网站Cookie 我们可以借助浏览器的扩展来获取Cookie信息 但其实通过浏览器本身的功能就可以查看Cookie信息 以Chrome类浏览器为例有以下三种方法 chrome浏览器 方法一 1 打开

随机推荐

  • 数据库为何要有复合主键(多主键)

    最近学习一点数据库的基本知识 xff0c 被一个问题困惑了许久 xff1a 主键是唯一的索引 xff0c 那么为何一个表可以创建多个主键呢 xff1f 其实 主键是唯一的索引 这话有点歧义的 举个例子 xff0c 我们在表中创建了一个ID字
  • @JSONField 注解详解和应用

    讲到 64 JSONField 注解 xff0c 就不得不提到Alibaba 开源的fasejson fastjson是目前java语言中最快的json库 xff0c 比自称最快的jackson速度要快 xff0c 第三方独立测试结果看这里
  • 外部访问docker容器(docker run -p/-P 指令)

    容器中可以运行一些网络应用 xff0c 要让外部也可以访问这些应用 xff0c 可以通过 P xff08 大写 xff09 或 p xff08 小写 xff09 参数来指定端口映射 xff08 1 xff09 当使用 P 标记时 xff0c
  • 解决Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)的序列化问题

    LocalDate LocalTime LocalDateTime 是Java 8开始提供的时间日期API xff0c 主要用来优化Java 8以前对于时间日期的处理操作 然而 xff0c 我们在使用Spring Boot或使用Spring
  • gcc 编译选项

    原来 Os相当于 O2 5 是使用了所有 O2的优化选项 xff0c 但又不缩减代码尺寸的方法 ffunction sections fdata sections Place each function or data item into
  • RYU功能开发(一)从simple switch开始

    对于任意一款控制器 xff0c 想要快速了解其开发机制 xff0c 从转发模块入手无疑是最佳的学习方式 RYU通过App的形式提供了一系列功能模块 xff0c 其中包括使用了OpenFlow作为控制协议的二层交换机控制模块simple sw
  • arm-linux-gcc交叉工具链

    Linux ARM交叉编译工具链制作过程 一 下载源文件 源代码文件及其版本与下载地址 xff1a Binutils 2 19 tar bz2 Index of gnu binutils gcc 4 4 4 tar bz2 Index of
  • 我使用过的Linux命令之cal - 显示日历

    我使用过的Linux命令之cal 显示日历 本文链接 xff1a http codingstandards iteye com blog 807962 xff08 转载请注明出处 xff09 用途说明 cal命令可以用来显示公历 xff08
  • 驼峰式与下划线命名规则

    在实际代码开发过程中 xff0c 代码编写格式清晰与否不仅决定了自己的代码编写与维护成本 xff0c 也直接影响到项目的开发进度 编码中常用的有驼峰法和下划线两种编码格式 xff0c 其中驼峰法常用在面向对象的高层语言中 xff0c 下划线
  • 全图文分析:如何利用Google的protobuf,来思考、设计、实现自己的RPC框架

    文章目录 一 前言二 RPC 基础概念1 RPC 是什么 xff1f 2 需要解决什么问题 xff1f 3 有哪些开源实现 xff1f 三 protobuf 基本使用1 基本知识2 使用步骤 四 libevent1 libevent 简介2
  • 针对vue的配置文件

    针对vue的配置文件 我们在根目录下创建一个 vue config js 文件 xff0c 将下方配置下去 module exports 61 区分打包环境与开发环境 process env NODE ENV 61 61 61 39 pro
  • Linux | LVM | 对比三种逻辑卷(Logic Volume)

    概述 为了满足在性能和冗余等方面的需求 xff0c LVM支持了下面三种Logic Volume xff1a Linear Logic Volume 线性逻辑卷Striped Logic Volume 条带化逻辑卷Mirror Logic
  • MySql ERROR 1129

    ERROR 1129 HY000 Host 39 mysql02 39 is blocked because of many connection errors unblock with 39 mysqladmin flush hosts
  • SpringBoot整合Shiro

    Apache Shiro是一个强大且易用的Java安全框架 执行身份验证 授权 密码学和会话管理 相比较Spring Security xff0c shiro有小巧 简单 易上手等的优点 所以很多框架都在使用shiro Shiro包含了三个
  • PB数据窗口对象之Button

    Button 重要属性 Action 属性 该属性是Button 控件最重要的一个属性 在数据窗口画板中 xff0c 可以选择一个按钮有哪个动作 可选的动作都是事先定义好的 xff0c 开发人员没有机会精确定义某个动作的执行 xff0c 只
  • 聊聊前端八股文?

    大家好 xff0c 我是若川 xff0c 点此加我微信进源码群 xff0c 一起学习源码 同时可以进群免费看Vue专场直播 xff0c 有尤雨溪分享 Vue3 生态现状以及展望 前些天 xff0c 我看到 剑指前端offer 一系列文章 x
  • 新手向:前端程序员必学基本技能——调试JS代码

    1前言 大家好 xff0c 我是若川 最近组织了源码共读活动 xff0c 感兴趣的可以加我微信 ruochuan12 参与 xff0c 已进行三个月了 xff0c 大家一起交流学习 xff0c 共同进步 想学源码 xff0c 极力推荐之前我
  • 全新的 Vue3 状态管理工具:Pinia

    大家好 xff0c 我是若川 最近组织了源码共读活动 xff0c 感兴趣的可以点此加我微信 ruochuan12 参与 xff0c 每周大家一起学习200行左右的源码 xff0c 共同进步 同时极力推荐订阅我写的 学习源码整体架构系列 包含
  • 推荐2022前端必看的新书 《Vue.js设计与实现》

    大家好 xff0c 我是若川 持续组织了6个月源码共读活动 xff0c 感兴趣的可以点此加我微信 ruochuan12 参与 xff0c 每周大家一起学习200行左右的源码 xff0c 共同进步 同时极力推荐订阅我写的 学习源码整体架构系列
  • 面试官问:跨域请求如何携带cookie?

    大家好 xff0c 我是若 川 持续组织了6个月源码共读活动 xff0c 感兴趣的可以点此加我微信 ruochuan12 参与 xff0c 每周大家一起学习200行左右的源码 xff0c 共同进步 同时极力推荐订阅我写的 学习源码整体架构系