首页 > 解决方案 > AJAX 访问代理提供的基本身份验证后的节点 API

问题描述

我得到了一个用 node.js 编写的普通 API,例如:

const express = require('express')
const app = express();

app.post('/api/data', (req, res) => {
  res.status(200).json({
    data: [1,2,3,3,1,3,5,2,3,4,4,7]
  })
})

app.use('/gui', express.static('./gui'))

app.listen(8080, () => { console.log("OK") })

和一个客户端javascript代码使用该fetch函数访问它,这种方式(例如./gui/index.html):

fetch('/api/data', {
  method: 'post',
  headers: {
    'Accept': 'application/json', 'Content-Type': 'application/json'
  },
  body: JSON.stringify(json)
})
.then( res => { console.log(res })

它工作得很好,但现在我想把这个 API 放在基本身份验证后面,而不用改变 API 代码,使用 nginx 作为中间人。配置文件如下所示:

server {
  listen 80;

  location / {
    auth_basic "Private Area";
    auth_basic_user_file .htpasswd; 

    proxy_pass http://localhost:8080;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
  }
}

现在,当我在浏览器中打开页面时,它会询问身份验证信息,显示 HTML,但 AJAX 访问失败并出现 401 错误。

检查后,浏览器似乎没有为 AJAX 访问发送授权标头。

问题是:有没有办法使基本身份验证对我的 API 和 GUI 透明?我做错了什么?

编辑

有人建议这个问题是Basic authentication with fetch 的副本?

我知道如何明确设置要获取的标题。我想要的是浏览器在应用程序落后于基本身份验证时隐式设置它们,而不需要对我的客户端代码进行任何修改。

标签: node.jsajaxhttpnginx

解决方案


正如@Tomalak 所建议的那样,并根据https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

默认情况下,fetch 不会从服务器发送或接收任何 cookie,如果站点依赖于维护用户会话(要发送 cookie,必须设置凭据 init 选项),则会导致未经身份验证的请求。

换句话说,我所要做的就是修改我的调用以获取这种方式:

fetch('/api/data', {
  credentials: 'include',
  method: 'post',
  headers: {
    'Accept': 'application/json', 'Content-Type': 'application/json'
  },
  body: JSON.stringify(json)
})
.then( res => { console.log(res) })

请注意credentials: 'include'in fetch 选项(可以使用same-origin而不是include更严格的安全性)。

这样,浏览器将在必要时隐式设置 auth 标头。


推荐阅读