问题1: Chrome 里的请求报错 “CAUTION: Provisional headers are shown” 是什么意思?

原回答:
情况:前后端分离项目中接口请求需要进行跨域处理,跨域请求的话浏览器会自动发出一个 OPTIONS 请求,然后返回允许该域名进行请求的相关信息后会再发出 GET 或者 POST 请求。我在 axios 的初始化处统一设置了 timeout 时间为 5s,然后由于后端人员没有针对 OPTIONS 请求进行单独处理,在 OPTIONS 请求时也进行了业务代码的执行,导致请求返回时间过长,有时候超过了 timeout 时间,因此后面的 GET 或者 POST 请求就没有发送成功,出现了 provisional headers are shown 的问题。

原解决方案:
解决:后端对 OPTIONS 请求进行了判断,不需要处理任何直接返回,速度快了很多,也就没有再出现上面的问题了。

本人出现问题:
也是前后端分离的开发模式, 打算发一个ajax请求, 测试自己写的express后端API, 实现session鉴权和状态登录, 但一直报错, 所以和上面这个问题较为相似. (自己写的原生代码就是垃圾, 第二天用jQuery库写Ajax, 各种bug都消失了…真的是佛了)

问题2:TypeError: Cannot read properties of undefined (reading ‘username’)

期间还遇到一个问题, 就是一直报如下错误

TypeError: Cannot read properties of undefined (reading 'username')

将 req.body打印出来为undefined, 所以报上述错误. 但明明表单数据有post给服务器… 后面发现 req.body: 通常用来解析POST请求中的数据, 不是nodejs默认提供的,需要载入中间件body-parser中间件才可以使用. 即没有注册中间件, 请求体为服务器端无法进行解析的MIME类型, 此外, 官方也给出了解释

Express官方文档:

req.body contains key-value pairs of data submitted in the request body. By default, it is undefined, and is populated when you use body-parsing middleware such as express.json() or express.urlencoded().

所以以下两种方案, 可以解决问题

//方案1
// For parsing application/x-www-form-urlencoded
app.use(express.urlencoded({extended: true
}))
//方案2
// 载入中间件body-parser中间件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended: false
}))

总结: 使用中间件, 请求体默认格式为字符串application/x-www-form-urlencoded, 可以添加express.urlencoded解析请求体, 也可以使用解析post表单数据的中间件body-parser

问题3: 静态资源托管无效

还发现我用了一个很傻的方式去渲染页面, 就是用Node.js内置模块去读取html页面的内容作为res.send响应体, 但实际上只需要将所有页面都放到pages文件夹下, 使用内置中间件express.static托管静态资源即可. 但也出现了一个很傻的bug:

app.use(express.static('./pages'))

改成下面写法, 就完全正确了, 可以url正常访问

app.use(express.static('pages'))

还会遇到一个问题: Node.js问题——req.session.user 与浏览器刷新.

我的代码里, 用户登录成功后就跳转到首页, 发送一个get请求, 调用api/username, 获取session存储的username, 然后在首页上方显示: username, 欢迎您. 但打印req.session居然没有username这个属性, 我悟了, 难道session不是每个页面共享的吗??? 我前脚在登录页设置了session.islogin属性, 后脚在首页就session.islogin undefined…
然后吧, 我发现我智障了, 我是用postman测试的api/username, 当然不存在session.islogin…

session确实就是整个站点共享的啊, 这也是session解决http无状态性的根本… 至于页面刷新就不存在session.islogin, 那是因为session的存活时间太短了, 刷新后就生成了新的session了, 去掉session里设置cookie的Max-Age

补充知识点: 原生node中怎么获取get/post请求参数

在这里在补充一个知识点, 部分参考原生node中怎么获取get/post请求参数:

  1. req.body: 通常用来解析POST请求中的数据, req.body不是nodejs默认提供的,需要载入中间件body-parser中间件才可以使用
  2. req.query: 由nodejs默认提供,无需载入中间件,此方法多适用于GET请求,解析GET请求中的参数, 包含在路由中每个查询字符串参数属性的对象,如果没有则为{}
  3. req.params: nodejs默认提供,无需载入其他中间件, req.params包含路由参数(在URL的路径部分),而req.query包含URL的查询参数(在URL的?后的参数)。
  4. req.session: 当express-session中间件配置成功后, 可以使用req.session来访问和使用session对象, 从而存储用户信息
  5. req.user: 当express-jwt中间件配置成功后, 可以使用 req.user 获取用户信息,并使用 data 属性将用户信息发送给客户端

问题4: 又写了JWT鉴权, 但读取req.user一直是undefined…

session是对cookie的补充, JWT是对session的补充, 安全性层层拔高, 任何一个新事物都是解决某一问题, 又产生另一问题, 选择何种方式进行鉴权取决于 你的侧重点是什么.
因为session还是使用了cookie存储SessionID, 存在跨域问题, 需要很多额外的配置, 同时session占用服务器的内存, 所以需要redis多个服务器共享该session, 把身份认证这件事又搞麻烦了. 于是诞生了JWT, 使用了H5新增的Web Storage, 服务器将身份认证信息加密给客户端存储, 又解决了服务器内存占用的问题, 同时没使用cookie跨域也解决了. 但因为添加了Authorization新的请求头, 所以又会产生预检请求, 服务器端要做相应的处理…

写JWT鉴权的代码, 需要准备以下材料: 2个中间件, 一个负责用户身份信息加密, 一个负责客户端发来的JWT解析为json, 还要定义秘钥(就是一个字符串).
参考代码又不全, 自己写了一个下午, 终于把思路理清楚, 踩的坑也解决了, 对JWT的理解也更深了, 所以就不一一展开对问题解释分析了, 直接将完整, 可运行代码粘在下面. 亲测有效.

JWT的express框架身份认证完整代码

// 1.导入用于生成JWT字符串的包
const jwt = require('jsonwebtoken')
// 2.导入用于将客户端发送的JWT字符串,解析还原为JSON对象的包
const expressJWT = require('express-jwt')
// 3. 定义secret秘钥, 保证JWT字符串的安全性
const express = require('express')
// 创建服务器实例
const app = express();
//允许跨域资源享用
const cors = require('cors');
app.use(cors())//解析post表单数据的中间件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended: false
}))
//2. 定义secret秘钥
const secretKey = 'huangrong'//注册将 JWT 字符串解析还原成 JSON 对象的中间件
app.use(expressJWT({secret: secretKey,algorithms: ["HS256"],requestProperty: "auth",  //res.auth.username就可以拿到用户名了, 默认是usercredentialsRequired: false, //是否允许未认证用户访问getToken: function fromHeaderOrQuerystring(req) {  //验证tokenif (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {return req.headers.authorization.split(' ')[1];} else if (req.query && req.query.token) {return req.query.token;}return null;}
}).unless({  //肯定登录页面是不用JWT鉴权的, 不然就是死循环了path: [{url: '/login',  method: ['GET', 'POST']},[/^\/api\//]   //调用api也不用JWT健全]
}));app.use(express.static('pages')) //托管静态资源, 我自己就做了2个页面, index和login//登录接口
app.post('/api/login', (req, res) => {//需要载入中间件body-parser中间件才可以使用req.bodyconst userinfo = req.bodyconsole.log(userinfo);if (userinfo.username !== 'admin' || userinfo.password !== '000000') {return res.send({status: 1,msg: '登陆失败!'})}// 用户成功登录后, 生成JWT字符串, 通过token属性响应给客户端//token: 调用 jwt.sign()生成JWT字符串, 三个参分别为 用户信息对象, 加密秘钥, 配置对象:当前 token 的有效期 const tokenStr = jwt.sign({username: userinfo.username}, secretKey, {expiresIn: '1d'  //token过期时间, 好像比较难手动注销JWT, 具体自己查一下})res.send({status: 0,msg: '登陆成功!',token: tokenStr //生成的token加密字符串, 三部组成: header + payload + Signature, 只有中间是真正信息})
})//这是一个有权限的API接口, 为什么说有权限, 是因为JWT验证成功, 服务器才能获取req,auth, 因为这个路径不在unless里
app.get('/admin/getinfo', (req, res) => {//使用 req.user 获取用户信息,并使用 data 属性将用户信息发送给客户端console.log(req.auth);  res.send({status: 1,msg: '获取用户信息成功',data: req.auth //要发送给客户端的用户信息})
})//6. 使用全局错误处理中间件, 捕获JWT失败后产生的错误, 建议测试代码, 不要用, 完全没办法定位错误了!!!!
// app.use((err, req, res, next) => {//     if (err.name == 'UnauthorizedError') {//         return res.send({//             status: 401,
//             msg: '无效的token'
//         })
//     }
//     next();
//     // res.send({//     //     status: 500,
//     //     msg: '未知的错误'
//     // })
// })app.listen(3000, () => {console.log('Express server running at http://127.0.0.1:3000')
})

Session的express框架身份认证完整代码

const express = require('express');
const app = express();
// 1. 导入session中间件
var session = require('express-session')
const cors = require('cors');// 2. 配置Session中间件  session不要写在路由的下方
app.use(session({secret: 'keyboard cat', //secret可以为任意字符串resave: false, //固定写法saveUninitialized: true, //固定写法cookie: {maxAge: 1000 * 30 * 3}
}))app.use(cors())
// 托管静态资源
app.use(express.static('pages'))
// For parsing application/x-www-form-urlencoded 解析post提交的表单数据
app.use(express.urlencoded({extended: false
}))//3. 向session中存数据
//当express-session中间件配置成功后, 可以使用req.session来访问和使用session对象, 从而存储用户信息
app.post('/api/login', function (req, res) {// res.json(req.body)console.log(req.body);if (req.body.username !== 'admin' || req.body.password !== '000000') {return res.send({status: 1,msg: '登陆失败'})}//只有成功配置express-session中间件, 才有req.session属性req.session.user = req.bodyreq.session.islogin = trueconsole.log(req.session)res.send({status: 0,msg: '登录成功'})
})
//获取用户姓名的接口
app.get('/api/username', (req, res) => {console.log(req.session);//判断用户是否登录if (!req.session.islogin) {return res.send({status: 1,msg: 'fail'})}res.send({status: 0,massage: 'success',username: req.session.user.username})
})
//退出登录接口
app.post('/api/logout', (req, res) => {req.session.destroy()res.send({status: 0,msg: '退出登录成功'})
})app.listen(3000, () => {console.log('CORS-enabled web server listening on port 3000');
})

【22/04】Chrome 里的请求报错 “CAUTION: Provisional headers are shown“ 是什么意思?相关推荐

  1. Provisional headers are shown in Chrome network tab

    Created by Wang, Jerry on Oct 15, 2015 细心的同学应该留意到,新版开发者工具的 Network 面板中,某些请求头后面会跟着下面这行文字: 截图是访问 http: ...

  2. Chrome v39 问题 Provisional headers are shown

    1,网站突然访问不到图片了. 发现: Provisional headers are shown 解决:删除chrome ,然后重启chrome即可. 第一个 http 请求实际上根本没有产生,对应的 ...

  3. Chrome插件请求数据时 请求报错(blocked:mixed-content)

    Chrome插件请求数据时请求报错(blocked:mixed-content) 问题原因 解决方案 方案1:配置https 方案1:使用background.js请求http 问题原因 问题原因是我 ...

  4. 请求报错No route to host (Host unreachable)

    请求报错No route to host (Host unreachable); nested exception is java.net.NoRouteToHostException: No rou ...

  5. ajax jsonp请求报错not a function的解决方案

    ajax jsonp请求报错not a function的解决方案 参考文章: (1)ajax jsonp请求报错not a function的解决方案 (2)https://www.cnblogs. ...

  6. python https请求报错:SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] 解决方法

    python爬虫,使用requests库发送https请求报错:SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] 解决方法: imp ...

  7. Here Document和Expect概述(免交互,变量设定,控制,注释,)(shell里使用EOF报错)

    文章目录 Here Document概述 Here Document使用注意事项 Here Document免交互 Here Document变量设定 Here Document格式控制 Here D ...

  8. ajax请求接口连不上会报错吗_服务端有异常, 导致: Ajax 请求报错 net::ERR_INCOMPLETE_CHUNKED_ENCODING...

    服务端有异常, 导致: Ajax 请求报错 net::ERR_INCOMPLETE_CHUNKED_ENCODING 但是,这个 Ajax Http 接口使用浏览器可以直接返回.表明,Ajax 的 G ...

  9. 【亲测成功】Ubuntu18.04升级GLIBC2.27——解决报错:ibc.so.6: version `GLIBC_2.28‘ not found

    [亲测成功]Ubuntu18.04升级GLIBC2.27--解决报错:/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found 事 ...

  10. ubuntu16.04挂载三星T5移动硬盘报错

    ubuntu16.04挂载三星T5移动硬盘报错 首先查看硬盘信息 sudo fdisk -l | grep NTFS 例如输出如下信息: /dev/sdd1 2048 97677021 9767680 ...

最新文章

  1. Mac下搭建solr搜索引擎与PHP扩展开发(上)
  2. 五种常见的 PHP 设计模式
  3. linux安装apache的纠结过程
  4. 成对的交换链表的节点 Swap Nodes in Pairs
  5. linux系统常用快捷键,文件类型,后缀名,语言修改,转义
  6. 用 SOLID 原则保驾 React 组件开发
  7. DE19 Introduction to the Laplace Transform
  8. [转载] Python之Numpy模块中的方法详解
  9. android listview 只加载显示的图片大小,Android ListView只加载当前屏幕内的图片(解决list滑动时加载卡顿)...
  10. Delphi XE 操作sqlite数据库
  11. 《金字塔原理》读书笔记
  12. 微信小程序:收款码三合一制作微信小程序源码下载多模板选择
  13. pdf打印机如何加密pdf文件?
  14. linux用ping命令测试网速,Linux通过终端测试网速
  15. 7-11 秋天的第一杯奶茶 (20 分)
  16. CUDA学习笔记(三)——共享内存
  17. 使用Unity实现时光倒流
  18. [Contrastive Learning] Improving Contrastive Learning by Visualizing Feature Transformation
  19. Unity - 画质设置
  20. ffmpeg与ffdshow的关系

热门文章

  1. 电路设计之8:MOS管驱动设计
  2. 力扣36.有效的数独
  3. 周董演唱会为什么总是抢不到票?教你用Python做一个自动抢票脚本
  4. 荣耀5G,三刀拍案惊奇
  5. 神经机器翻译中有用的技巧
  6. 中文语音合成TTS (TensorFlowTTS)免费API资源及DEMO
  7. 语音合成 TTS 相关的一些总结
  8. 计算机硬盘上的文件打不开,电脑硬盘打不开怎么办
  9. Spring Transaction : TransactionInterceptor
  10. c语言表达式判断语法错误题,大连理工大学C语言模拟题机房题库单选、判断、填空(分章节_共十一章)...