带有 Angular 和 Express 的 CORS - 在 Postman 中工作,但不在浏览器中

Posted

技术标签:

【中文标题】带有 Angular 和 Express 的 CORS - 在 Postman 中工作,但不在浏览器中【英文标题】:CORS with Angular and Express - Working in Postman but not in the browser 【发布时间】:2018-05-30 12:40:11 【问题描述】:

我遇到了与 CORS 相关的问题(我认为),当我从邮递员发送登录帖子请求时,它会成功。当我尝试使用我的 Angular 2 前端应用程序登录时,请求状态似乎是 200,但没有任何反应,并且在控制台中我收到一条奇怪的消息,提示我的 localhost:4200 是不允许的,我该如何解决这个问题?

Angular http 方法

 authenticateUser(user)
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    return this.http.post('http://localhost:3000/api/authenticate', user, headers: headers)
    .map(res => res.json());
  

来自控制台的错误消息。

邮递员请求(成功)

如果这是与快递相关的问题,这里是我的快递代码:

const express = require("express")
const bodyParser = require("body-parser")
const logger = require('morgan')
const api = require("./api/api")
const path = require('path')
const secret = require('./models/secrets')
const expressJWT = require('express-jwt')
const cors = require('cors');

const app = express()

app.set("json spaces", 2)
app.use(logger("dev"))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded( extended: false ))

app.use(expressJWT(secret: secret).unless(path : ['/api/authenticate', '/api/register']))

app.use("/api/", api)

app.use(function (req, res, next) 
  var err = new Error('Not Found')
  err.status = 404
  next(err)
)

app.use(function (err, req, res, next) 
  console.error(err.status)
  res.status(err.status || 500)
  res.json( msg: err.message, status: err.status )
)

// Body Parser middleware
app.use(bodyParser.json());

// CORS middleware
app.use(cors());

// set static folder
app.use(express.static(path.join(__dirname, 'public')));
//Call this to initialize mongoose
function initMongoose(dbConnection) 
  require("./db/mongooseConnect")(dbConnection)


app.initMongoose = initMongoose

module.exports = app

/authenticate 的路由看起来像这样

// Authenticate
router.post('/authenticate', (req, res, next) => 
    const username = req.body.username;
    const password = req.body.password;

    User.getUserByUsername(username, (err, user) => 
        if (err) throw err;
        if (!user) 
            return res.json( success: false, msg: 'User not found' );
        

        User.comparePassword(password, user.password, (err, isMatch) => 
            if (err) throw err;
            if (isMatch) 
                const token = jwt.sign(data: user, secret, 
                    expiresIn: 604800 // 1 week
                );

                res.json(
                    success: true,
                    token: 'Bearer ' + token,
                    user: 
                        id: user._id,
                        name: user.name,
                        username: user.username,
                        email: user.email
                    
                );
             else 
                return res.json( success: false, msg: 'Wrong password' );
            
        );
    );
);

【问题讨论】:

【参考方案1】:

我花了一些时间才找到它,如果在JSON.stringify(PostData) 之后发出的帖子请求会与节点应用程序的正文解析器冲突并给出一个空正文。

【讨论】:

【参考方案2】:

发出的请求称为preflight request - 您可以在错误消息中看到这一点,其中指出对预检请求的响应未通过访问控制检查。预检请求由浏览器发出,因为 CORS 只是浏览器安全限制 - 这就是它在 Postman 中工作的原因,当然,不是浏览器。

您正在使用的 CORS 中间件的 docs 说明如下:

要启用预飞行,您必须为要支持的路线添加一个新的 OPTIONS 处理程序:

在您的情况下,由于您已将 CORS 处理设置为适用于所有来源等,您可以使用以下内容(同样来自文档):

app.options('*', cors()) // include before other routes

正如评论所述,您需要将其移至 .js 文件的顶部,以便首先对其进行处理。

还建议专门设置允许的来源、路由等,以锁定哪些来源能够访问哪些端点。您可以使用自己喜欢的搜索引擎阅读更多相关信息。

【讨论】:

谢谢!我没想过,但顺序是问题。我移动了 app.use(cors());直到 expressJWT 中间件之前和 app.use("/api/", api) 之前。这最终解决了问题。不过,我不必添加“*”。 好的,很酷。感谢您提供额外的信息。那里的文档有点误导,但如果你直接去解释simple usage的地方,它确实建议app.use(cors())应该处理所有请求,正如你所说的。跨度>

以上是关于带有 Angular 和 Express 的 CORS - 在 Postman 中工作,但不在浏览器中的主要内容,如果未能解决你的问题,请参考以下文章

带有 Angular 和 Express 的 CORS - 在 Postman 中工作,但不在浏览器中

Angular - 错误类型错误:_co.timeIn 不是函数

本地主机上带有 Angular 的 NodeJS + Express:被 CORS 预检阻止

Cookie 中的 Angular JWT 如何防止 CSRF/XSRF 和 XSS

使用 angular 和 express-jwt 实现刷新令牌

使用 nodejs/express 登录后将用户重定向到 Angular 应用程序