likes
comments
collection
share

Node.js实现JWT获取不到请求头的Authorization,同源策略与预检请求

作者站长头像
站长
· 阅读数 32

问题

今天在练习node.js实现JWT的时候,出现了一个怪问题:

下面是前端设置Authorization的代码:

request.interceptors.request.use(
    config => {
        const token = localStorage.getItem('token')
        config.headers.Authorization = `Bearer ${token}`
        return config
    },
    error => {
        return Promise.reject(error)
    }
)

随后调了一个get /test的测试接口

后端测试代码:

const testRouter = require('./test')

router.use((req, res, next) => {
    console.log('headers1:', req.headers)
    res.set({
        'Access-Control-Allow-Origin': 'http://localhost:3000',
        'Access-Control-Allow-Methods': '*',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    })
    next()
})

router.use(testRouter)

这里处理了一下跨域,随后调用testRouter:

const express = require('express')
const router = express.Router()

const { verifyToken } = require('../utils/token')
router.use(verifyToken)

router.get('/test', async (req, res) => {
    res.status(200)
    res.send({ msg: 'test success', code: 2000, data: {} })
})

module.exports = router

这里调用了方法验证token,方法如下:

const verifyToken = async function (req, res, next) {
    console.log(req.headers.authorization)
    const token = req.headers.authorization.split(' ')[1]
    jwt.verify(token, secretKey, function (err, decoded) {
        if (err) {
            console.log('verify error', err)
            res.status(200)
            return res.send({ code: 4004, msg: 'token无效' })
        }
        console.log('verify decoded', decoded)
        next()
    })
}

随后我写完代码开始测试,我发现 req.headers.authorization 怎么都打印不出来;

然后我在路由入口的中间件打印了一下req.header,我发现设置的Authorization根本不在header里,我就觉得很奇怪了,但是我又发现header打印了两次,诶,很怪,为什么会打印两次吖?

我突然想到,当前端使用axios发起请求时,浏览器检测到不是简单请求,就会发起一个预检请求,这样的话我后端的中间件首先会收到两次请求,而且因为没有特意去处理预检请求,所以预检请求会跟着中间件走下去,随后进入到token验证的方法里,预检请求当然没有设置的authorization,这样就会导致找不到authorization而报错。

解决方法

在路由入口的中间件下处理掉预检请求options,返回掉他。

router.options('*', (req, res) => {
    res.status(200).send({ msg: '测试通过' })
})

简单与预检请求

不会触发 CORS 预检请求。这样的请求为 简单请求 。

  1. HTTP 方法限制:只能使用 GET、HEAD、POST 这三种 HTTP 方法之一。
  2. 自定义标头限制:请求的 HTTP 标头只能是以下几种常见的标头:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type(仅限于 application/x-www-form-urlencodedmultipart/form-datatext/plain)。
  3. HTML 头部 header field 字段:DPR、Download、Save-Data、Viewport-Width、WIdth。
  4. 不使用自定义请求标头:请求不能包含用户自定义的标头。
  5. 请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

其他的请求都是预检请求。

预检的请求要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,随后服务器返回允许跨域以及一系列的请求头信息到浏览器,接下来才能进行正常的请求响应。

转载自:https://juejin.cn/post/7370841518792458275
评论
请登录