Node.js:新创建的标头(res.header)未出现在 Chrome 中

Posted

技术标签:

【中文标题】Node.js:新创建的标头(res.header)未出现在 Chrome 中【英文标题】:Node.js : newly created header (res.header) not appearing in Chrome 【发布时间】:2020-06-24 09:34:05 【问题描述】:

我对 javascript、Express 和 NodeJS 还很陌生。我在用户登录时尝试创建包含令牌的新标头时遇到问题(如下登录 POST 路由器中所示

// Login POST Router
router.post('/login', async (req, res) => 

    // 1. Validatation
    const error = loginValidation(req.body)
    // if has error don't save
    if(error) return res.status(400).send(error.details[0].message)

    // 2. Check the existance of user/email in db
    const userEmail = await User.findOne(email: req.body.email)
    // if 'same/exist', then throw 'message/error'
    if(!userEmail) return res.status(400).send(`Email doesn't exist!`)

    // 3. Chack password (is correct)
    const validPassword = await bcrypt.compare(req.body.password, userEmail.password)
    if(!validPassword) return res.status(400).send(`Invalid password!`)

    // 4. Create & assign token to user
    const token = jwt.sign(_id: userEmail._id, process.env.TOKEN_LOGINUSER)
    // add 'token' to header - just for identifier (can be any name)
    res.header('auth-token', token).json( message: 'Logged In')
)

然后发出获取请求的登录页面(login.js 用 Vanilla JavaScript 编码)将重定向到主页(如图所示下面在 login.js - 登录页面)

if(loginRespond === 'Logged In') 

    let homeURL = '/index.html'
    window.location.replace(homeURL)
 

然后回到 NodeJS,我有一个用于 home 或 '/' 的路由器,它首先使用一个函数来验证令牌(如下所示

router.get('/', verify, async (req, res) => 

    const data = await All.findById( _id: req.user._id)
    res.json(data.data)
)

并具有 JSON Web 令牌验证功能如下图

// Middleware function
function verify(req, res, next) 

    // get token from header
    const token = req.header('auth-token')
    // if have, then allow. If don't have, then don't allow
    if(!token) return res.status(401).json( message: 'Accessed denied!' )

    try 

        // verify the exist token
        const varified = jwt.verify(token, process.env.TOKEN_4LOGINUSER)
        req.user = varified
        next()
     catch(err) 
        res.status(400).json( message: 'Invalid token!' )
    

这些是我的中间件

// B. Global Middleware
// 1. Handle cors
app.use(cors())
// 2. Handle JSON body-parser
app.use(express.json())

使用 Postman 进行测试时一切正常。但不幸的是,没有现场直播。由于 auth-token 从未创建,并且无法在 Chrome 主页的 Response Header 中找到(如下所示

由于我是 express 和 nodejs 的新手,我实际上不知道如何解决这个问题。我已经尝试通过谷歌搜索它。但是找不到要搜索的正确句子或关键字。

希望你们能指出我在哪里看,在尝试这样做之前我应该​​阅读或学习什么。

【问题讨论】:

【参考方案1】:

您需要通过添加 Access-Control-Expose-Headers 标头来公开您的自定义标头。

res
    .header('Access-Control-Expose-Headers', 'auth-token')
    .header('auth-token', token)
    .json( message: 'Logged In')

这是它在浏览器中工作所必需的,但对于 Postman 来说不是。

Access-Control-Expose-Headers 响应标头通过列出其名称来指示哪些标头可以作为响应的一部分公开。

作为替代方案,您可以为您的 cors 中间件提供自定义选项参数:app.use(cors( exposedHeaders: 'auth-token' ))。它需要一个逗号分隔的字符串(例如:'Content-Range,X-Content-Range')或数组(例如:['Content-Range', 'X-Content-Range'])。

关注documentation on this from MDN。

默认情况下,仅公开 7 个 CORS 安全列表响应标头:

缓存控制 内容-语言 内容长度 内容类型 过期 最后修改 编译指示

如果您希望客户端能够访问其他标头,则必须使用 Access-Control-Expose-Headers 标头列出它们。

【讨论】:

对不起,如果这个问题听起来很无知,我创建的 Middlewares app.use(cor()) 还没有涵盖自定义标头 - Access-Control-Expose-Headers cors 中间件将仅涵盖我的回答中描述的 7 个 CORS 安全列表标头。任何其他响应标头都需要 Access-Control-Expose-Headers 标头。 您还可以为您的 cors 中间件提供自定义选项参数:app.use(cors( exposedHeaders: 'auth-token' ))。它需要一个逗号分隔的字符串(例如:'Content-Range,X-Content-Range')或数组(例如:['Content-Range', 'X-Content-Range'])。 两种方式都行不通。 auth-token 仍然无法在标头中注册。在重定向到home/index.html 页面之前,是否需要在login.js 中的提取接收端指定一些内容? auth-tokenindex.html 中不可用,并且无法将其作为“响应参数”传递,因为您使用的是重定向。您可以在重定向中将其作为获取参数index.html?auth-token=TOKEN 传递,然后以(new URL(window.location.href)).searchParams.get("auth-token") 访问它。但是,这是不好的做法,因为您会将用户对象作为 get 参数发送。

以上是关于Node.js:新创建的标头(res.header)未出现在 Chrome 中的主要内容,如果未能解决你的问题,请参考以下文章

使用 res.header express node js 的数组的正确方法是啥

node.js创建简单服务测试请求数据

node.js express配置允许跨域

一个简单的node.js

一个简单的node.js

node开发node.js编写一个接口