无法使用 Angular 7 将授权标头发送到节点 11/Express 4 服务器

Posted

技术标签:

【中文标题】无法使用 Angular 7 将授权标头发送到节点 11/Express 4 服务器【英文标题】:Cannot send Authorization header to Node 11 / Express 4 server using Angular 7 【发布时间】:2019-09-11 20:01:36 【问题描述】:

我无法通过 GET requestAuthorization 标头从我的角度前端发送到我的节点后端,它们位于同一个 VPS 上。

为了从 angular 发出请求,我使用

return this.httpClient.get<ApiResponse>(ApiClientService.apiAddress + ApiClientService.secureRoute + '/posts');

并使用 JwtModule 中的这个 http 拦截器在 app.module.ts 中设置授权标头

  imports: [
    ...,
    JwtModule.forRoot(
      config: 
        tokenGetter,
        whitelistedDomains: [ApiClientService.apiAddress, 'vps.ip.address:VPS_FRONT_PORT', 'localhost:BACK_PORT', 'localhost:FRONT_PORT'], //todo clean
      
    ),

当我在前面的铬检查器中查看请求时,我看到了

GET /secure/posts HTTP/1.1
Host: vps.ip.address:VPS_BACK_PORT
Connection: keep-alive
Accept: application/json, text/plain, */*
Origin: vps.ip.address:VPS_FRONT_PORT
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (Khtml, like Gecko) Ubuntu Chromium/73.0.3683.86 Chrome/73.0.3683.86 Safari/537.36
Referer: vps.ip.address:VPS_FRONT_PORT/posts
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,fr;q=0.8

我们注意到 Authorization 标头缺失


问题不是来自拦截器 IMO,因为

在发出相同的请求时,但对 google.com,我在 chrome 检查器中看到了 Authorization 标头 手动添加标头时,没有拦截器,我遇到了同样的问题

这让我认为问题来自我的 节点 服务器的 CORS/preflight 请求配置。 api.config.js

app.use(function (req, res, next) 
    res.header('Access-Control-Allow-Origin', '*, localhost, localhost:FRONT_PORT, vps.ip.address:VPS_FRONT_PORT'); //todo change *
    res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
    res.header('Access-Control-Allow-Credentials', true);
    next();
)

...

const secureApi = express.Router();
app.use('/secure', secureApi);
secureApi.use(checkToken);
ProblemRoute.init(secureApi);
PostRoute.init(secureApi);
app.use(function (err, req, res, next) 
    console.error(err.stack);
    res.status(500).send('Something broke!');
);
const ApiConfig = 
    app: app
;

module.exports = ApiConfig;

读取节点服务器上的授权标头。 secureRoute.js

const jwt = require('jsonwebtoken');

module.exports = function checkToken(req, res, next) 
    const authHeader = req.headers['authorization'];
    console.log(req.headers);
    if (authHeader.startsWith("Bearer ")) 
        const token = authHeader.substring(7, authHeader.length);

        if (token) 
            jwt.verify(token, 'my_secret_key', (err, decode) => 
                if (err) 
                    res.status(400).json(
                        "message": "Invalid token",
                    );
                 else 
                    next();
                
            )
         else 
            res.status(400).json(
                "message": "Token must be provided in header for endpoint access",
            );
        
     else 
        res.status(400).json(
            "message": "Token must be provided in header for endpoint access",
        );
    
;

这当然会导致 错误,因为角度前端请求中 缺少 Authorization 标头。

TypeError:无法读取未定义的属性“startsWith” 在 checkToken (/home/me/project/node-project/config/secureRoute.js:6:20)

当我使用 postman 发出类似请求时,它工作正常,这是 postman 开发者控制台日志

获取 /snap/postman/81/usr/share/Postman/resources/app/html/vps.ip.address:BACK_PORT/secure/posts 内容类型:application/json 缓存控制:无缓存 Postman-Token: 10a5caf7-711e-4c39-9437-58dd825ca05f 授权:承载 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtYWlsIjoicGF1bEBiZWxsb2Mub3ZoIiwiaWF0IjoxNTU1ODgzMjgxLCJleHAiOjE1NTU5Njk2ODF9.s6z5hBLJWEdlDgzw9E9ePiLWj9hqmd39RFLGLk68 用户代理:PostmanRuntime/7.6.0 接受:/ 主机:vps.ip.address:BACK_PORT 接受编码:gzip,放气

并且节点服务器按预期读取请求/标头并回答200和内容。

【问题讨论】:

【参考方案1】:

最后,我认为错误来自我配置错误的拦截器。我在白名单域中包含了“http://”部分,我相信这会导致它的行为不正确。

我也开始使用 cors npm 包,但我认为这不是解决办法。

【讨论】:

以上是关于无法使用 Angular 7 将授权标头发送到节点 11/Express 4 服务器的主要内容,如果未能解决你的问题,请参考以下文章

节点js [ERR_HTTP_HEADERS_SENT]:将标头发送到客户端后无法设置标头

防止 nuxt auth 将授权标头发送到外部 url

GraphQL 突变“在将标头发送到客户端后无法设置标头”

Firebase 云功能错误:“在将标头发送到客户端后无法设置标头”

如何解决“将标头发送到客户端后无法设置标头”

将标头发送到客户端后无法设置标头-Nodejs + AWS-S3 getObject