客户端读取响应头+后端读取请求头的那些事

news2024/9/29 7:26:25

在一些特殊场景中,我们在客户端想要去获取服务端接口设置的一些自定义响应头,服务端该如何处理,客户端才能取到这些自定义响应头的值呢?

特殊场景,我这里也举例一下,原生页面webView嵌入web页面。这个时候如果在app内,用户已经登录了,就需要h5页面能够拿到用户信息,但是登录信息在app中,所以需要原生把这个信息传递给h5页面。

这个时候会有两种方法,一个是通过接口请求的方式,我们指定尽管是一个页面,在浏览器打开,但其实本质是一个get请求。所以能够通过这个接口传递数据;第二个方法就是与h5页面进行通信。

通过接口请求,这里也有讲究,直接把数据传递在url里面,这样h5页面是肯定能拿到这个数据的,但是有个问题,就是把所有信息暴露出来,只有能够拿到链接,用户信息就全部暴露了;讲到这里应该很多人想到了使用数据加密,确实加密可以防御,但并不是最好的选择(尽管这个值被加密了,url上也仍然不理想,因为url有长度限制),因为加密肯定要能够解密,不然h5页面怎么取到数据,这个时候,仍然有暴露的风险;第二种方式就是将信息传递在接口响应头里,这样除非使用抓包,不然这个信息是拿不到,也显示不出来的。

所以通常在链接上不会随意携带敏感数据,但是技术方案时,就必须要区分,这个时候,大家都会想在响应头里面存放自定义数据,因为这样就只有能把这个接口抓包获取才知道的信息,普通用户无感知。

但是普通在服务端响应头增加自定义字段,在客户端直接读取是不行的,比如下面例子

客户端直接去读取响应头(response headers)

服务端代码:

app.all("*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Authorization', '1234');
  next();
})
app.get('/list', (req, res) => {
  res.send({
    list: [1,2,3,4],
    code: 200
  })
})

客户端代码:

const testHeader = () => {
  fetch('http://localhost:80/').then(res => {
    console.log(res.headers.get('Authorization')) // 读取请求头字段
    return res.json()
  }).then(res => {
    console.log(res)
  })
}
testHeader()

我们能够在控制台中看到这个属性,但是这个请求头的值,读取是null

所以这个时候,我们陷入沉思,请求接口时,我们知道能够在客户端定义请求头,但是在客户端去读取响应头字段,我们还真不会了

后端读取客户端请求头(request headers)

按理说客户端请求接口时,只有后端指定了有这个自定义请求头,前端就能在发送请求时,添加对应的自定义请求头字段

例如下面添加自定义请求头trackId

服务器端代码


app.all("*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Headers', 'trackId');

  next();
})
    

客户端代码

const testHeader = () => {
  fetch('http://localhost:80/list', {
                        headers: {
      'trackId': '200000001'
    },
  }).then(res => {
    console.log(res.headers.get('Authorization'))
    return res.json()
  }).then(res => {
    console.log(res)
  })
}
testHeader()

服务端接受前端返回的请求头

app.get('/list', function (req, res) { 
  console.log(req.headers)
  res.send({
    list: [1,2,3,4],
    code: 200
  })
})

这其实就是在后端接受请求头参数了,通常企业中都是这样来发送一些用户token,确保用户此刻是登录状态,通常也有来区分是哪个用户请求了这个接口

前端就自动去添加这个自定义请求头的时候,控制台会直接报错,请求会被浏览器拦截。请求不会发送到后端

可以直接看网络请求,请求被拦截了

谷歌浏览器控制台说明:https://developer.chrome.com/docs/devtools/network/reference/?utm_source=devtools#provisional-headers

询问一下chatGPT如何解决这个错误

就会发现需要后端设置这个自定义请求头字段

客户端正确读取服务端设置的响应头(response headers)

从上面的例子,我们发现前端不能直接设置自定义请求头,需要与后端接口协议好,这个接口需要传递哪些请求头字段,如果后端没有设置这个res.header(‘Access-Control-Allow-Headers’, ‘trackId’);

所以前端接受后端自定义的响应头字段,读取不到,问题出在后端

后端服务需要设置将自定义响应头字段暴露给客户端访问

响应标头 Access-Control-Expose-Headers

服务端代码

app.all("*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Headers', 'trackId');
  res.header('Access-Control-Expose-Headers', '*, Authorization'); // 允许暴露响应头数据给客户端
  res.header('Authorization', '1234');
  next();
})


app.get('/list', function (req, res) {
  console.log(req.headers)
  res.send({
    list: [1,2,3,4],
    code: 200
  })
})

客户端获取响应头字段

const testHeader = () => {
  fetch('http://localhost:80/list', {
    headers: {
      'trackId': '200000001'
    },
  }).then(res => {
    console.log(res.headers.get('Authorization'))
    return res.json()
  }).then(res => {
    console.log(res)
  })
}
testHeader()

好了,今天的分享就到这里结束了,如果你有任何疑惑,欢迎在评论区讨论,或者你有更好的方案,也可以在评论区分享一下~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/545891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Shell脚本编程入门--Day2

文章目录 几个简单内置shell命令shell字串的语法计算变量长度的各种玩法批量修改文件名特殊shell扩展变量实际应用父子shell创建进程列表(创建子shell) 几个简单内置shell命令 echo -n 不换行输出 -e 解析字符串中的特殊符号 (\n, \r, \t, \…

浏览器的进程和线程

浏览器是多进程多线程的应用程序 浏览器进程 主要负责界面显示、用户交互、子进程管理等。浏览器进程内部会启动多个线程处理不同的任务。 网络进程 负责加载网络资源。网络进程内部会启动多个线程来处理不同的网络任务。 渲染进程 渲染进程启动后,会开启一个染主线…

macOS 13.4正式版(22F66)With OpenCore 0.9.2开发版 and winPE双引导分区原版镜像

镜像特点 原文地址:http://www.imacosx.cn/113625.html 完全由黑果魏叔官方制作,针对各种机型进行默认配置,让黑苹果安装不再困难。系统镜像设置为双引导分区,全面去除clover引导分区(如有需要,可以自行直…

java boot项目基础配置之设置启动端口

因为 springboot 项目是一个内嵌的tomcat 那么 我们就来研究一下 怎么改它的启动端口 其实 它的配置 还是非常多的 我们基础部分讲一下 后面 到实用部分 再一边用 一边再看一些 首先 我们如果不设置 他就会占用 我们的 8080端口 那么 我们最好就直接用 80端口 就不用输入端口…

【滤波】卡尔曼滤波数学

本文主要翻译自rlabbe/Kalman-and-Bayesian-Filters-in-Python的第7章节07-Kalman-Filter-Math(卡尔曼滤波数学)。 %matplotlib inline#format the book import book_format book_format.set_style()简介 如果你已经学习到了这一步,我希望你…

vue基础知识一:说说你对vue的理解?

一、从历史说起 Web是World Wide Web的简称,中文译为万维网 我们可以将它规划成如下的几个时代来进行理解 石器时代 文明时代 工业革命时代 百花齐放时代 石器时代 石器时代指的就是我们的静态网页,可以欣赏一下1997的Apple官网 最早的网页是没有数据库…

day1 IO 模型

目录 基本概念 同步和异步 阻塞和非阻塞 线程在运行过程中,可能由于以下几种原因进入阻塞状态: 可能阻塞套接字的Linux Sockets API调用分为以下四种 五种 I/O 模型 阻塞I/O 非阻塞I/O ​编辑 I/O多路复用模型 信号驱动式I/O模型 异步I/O 模型 …

网络模块封装

网络模块封装 library-network模块配置依赖一.自定义LiveDataCallAdapterFactory1.定义ApiResponse返回的数据类型2.LiveDataCallAdapter.kt3.LiveDataCallAdapter.kt 二.自定义CustomGsonConverterFactory三.拦截器1.HeaderInterceptor请求头拦截器2.BasicParamsInterceptor参…

Android - 内容提供者(Content Provider) 使用

Android - 内容提供者(Content Provider) 内容提供者组件通过请求从一个应用程序向其他的应用程序提供数据。这些请求由类 ContentResolver 的方法来处理。内容提供者可以使用不同的方式来存储数据。数据可以被存放在数据库,文件,甚至是网络。 有时候需…

Python如何进行性能测试?(Locust对接口进行压测)

python如何进行性能测试呢?其实原理就是对于接口进行加线程,打个比方就是当你有一个电梯,你同时可以搭载多少个人坐电梯那这个人数就是这部电梯的其中一个性能指标,那么对于接口来说每秒钟能有多少人成功发起请求后得到成功的响应…

QT 学习笔记2 信号与槽

上次做的界面,并没有逻辑。你点击按钮,并不会执行什么 要想其能作出反映,就不得不提到一个很重要的机制---信号与槽 当我们点击确定的时候,按钮会发出一个信号 点击确定的时候,会执行一段代码,这段程序就…

Ada 语言学习(3)复合类型数据——Array

文章目录 Array数据类型声明数组索引数组范围数组复制数组初始化直接赋值通过拷贝赋值不同索引范围但长度相等非指定类型边界收缩 多维数组数组遍历数组切片访问和动态检查直接访问动态检查 数组字面量 Array literal数组拼接两个数组拼接数组和单个值拼接 Array Equality&…

机器学习平台 PAI 支持抢占型实例,模型服务最高降本 90%

助力模型推理服务降本增效,适用于推理成本敏感场景,如:AIGC 内容生成异步推理、批量图像处理、批量音视频处理等。 在 AI 开发及服务不断追求效率的背景下,阿里云机器学习平台 PAI 宣布支持抢占型实例(Spot Instance&a…

2023逆向分析代码渗透测试flag0072解析(超详细)

一、竞赛时间 180分钟 共计3小时 1.从靶机服务器的FTP上下载flag0072,分析该文件,请提交代码保护技术的类型。提交格式:XXXX。 2.提交被保护的代码所在地址。提交格式: 0xXXXX。 3.提交代码解密的密钥。提交格式: 0xXX。 4.请提交输入正确flag时的输出。提交格式: XXXX。…

Python入门(十二)while循环(二)

while循环(二) 1.使用while循环处理列表和字典2.在列表之间移动元素3.删除为特定值的所有列表元素4.使用用户输入来填充字典 作者:xiou 1.使用while循环处理列表和字典 到目前为止,我们每次都只处理了一项用户信息:获…

建站教程:腾讯云轻量服务器安装宝塔面板搭建网站流程

腾讯云轻量应用服务器镜像选择宝塔Linux面板,然后在宝塔面板上安装LNMP网站所需的Web环境,在宝塔面板上新建站点,上床网站程序安装包到根目录,并安装网站全流程。腾讯云百科来详细说下腾讯云轻量应用服务器搭建网站全流程&#xf…

百果园ESG:围绕“好吃”二字,勾勒水果行业未来蓝图

当一场可持续绿色变革开始,ESG(环境、社会与治理)已经成为企业发展战略的重要组成部分。 然而,如何实现ESG和企业发展的协同却是一大问题。根据毕马威《2022年中国首席执行官展望》,一些企业家也表示ESG投资对提升财务…

SpringBoot配置文件3种格式、配置文件读取方式、多环境配置、配置文件优先级分类

文章目录 1 配置文件格式1.1 环境准备1.2 不同配置文件演示1.3 三种配合文件的优先级 2 yaml格式2.1 语法规则 3 yaml配置文件数据读取3.1 环境准备3.2 读取配置数据方式1 使用 Value注解方式2 Environment对象方式3 自定义对象 4 多环境配置4.1 yaml文件4.2 properties文件4.3…

H.265/HEVC编码原理及其处理流程的分析

H.265/HEVC编码原理及其处理流程的分析 H.265/HEVC编码的框架图,查了很多资料都没搞明白,各个模块的处理的分析网上有很多,很少有把这个流程串起来的。本文的主要目的是讲清楚H.265/HEVC视频编码的处理流程,不涉及复杂的计算过程。…

自定义线程池 ThreadPoolExecutor

ThreadPoolExecutor 自定义线程池 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultT…