设置了节点标头但是一些用户遇到了访问控制错误

时间:2015-06-15 14:12:43

标签: javascript node.js

我有一个运行以下标头代码的节点服务器:

    app.all('/*', function (req, res, next) {
    // CORS headers
    res.header("Access-Control-Allow-Origin", "*"); // restrict it to the required domain
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    // Set custom headers for CORS
    res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
    if (req.method == 'OPTIONS') {
        res.status(200).end();
    } else {
        next();
    }
});

现在在许多计算机和浏览器上都可以正常工作(包括我自己的),但是没有坐在我办公室的人会收到以下错误消息:

enter image description here

好的,这很难读,所以这里有两个错误:

  1. 无法加载资源:Access-Control-Allow-Origin
  2. 不允许原始http://angular.mydomain.com
  3. XMLHttpRequest无法加载http://angular.mydomain.com:8080/login。 Access-Control-Allow_origin不允许来源http://angular.mydomain.com
  4. 谁能告诉我这里发生了什么?

    接头

    enter image description here

    登录路线:

    router.route('/login')
    .post(function (req, res) {
        var user = User.build();
    
        var username = req.body.username || '';
        var password = req.body.password || '';
    
        if (username == '' || password == '') {
            res.status(401);
            res.json({
                "status": 401,
                "message": "Invalid credentials"
            });
            return;
        }
        var salt = bcrypt.genSaltSync(10);
        var hash = bcrypt.hashSync(password, salt);
    
    
        user.retrieveByNamePassword(username, function (users) {
            var i = 0;
            if (bcrypt.compareSync(password, users.password)) {
                var log = User_Login.build()
                log.findLastLogin(users.id, function (result) {
                    users.last_login = result;
                    if (users.user_type_id > 3) {
                        res.json(genToken(users, null));
                    }
                    else {
                        var div = Division.build();
                        selected_user = users;
                        var root = [selected_user.division_id];
                        div.retrieveByDivisionId(selected_user.division_id, function (division) {
                            var result = [];
                            var root = [division];
                            (function loop() {
                                var element = root[0];
                                var divisions = Division.build();
                                divisions.retrieveByParentId(element.id, function (divisions) {
                                    if (divisions) {
                                        divisions.forEach(function (division) {
                                            root.push(division);
                                        });
                                        result.push(element.id);
                                        root.splice(0, 1);
                                        if (root.length > 0) {
                                            loop()
                                        }
                                        else if (root.length == 0) {
                                            res.json(genToken(users, result));
                                        }
                                    } else {
                                        res.send(401, "No division found");
                                    }
                                });
                            }());
                        })
                    }
                }, function (error) {
                    var i = 0;
                });
    
            } else {
                // If authentication fails, we send a 401 back
                res.status(401);
                res.json({
                    "status": 401,
                    "message": "Invalid credentials"
                });
                return;
            }
        }, function (error) {
            res.status(401);
            res.json({
                "status": 401,
                "message": "Invalid credentials"
            });
            return;
        });
    });
    

2 个答案:

答案 0 :(得分:0)

maybe he is receiving a 404 or similar code that represents an unreachable resource from this foreign network.

答案 1 :(得分:0)

这是表达尝试处理OPTIONS请求的情况。我建议在最后一段修改,但如果你想更全面地了解为什么会发生这种情况,请仔细阅读。

为什么会有OPTIONS个请求?这就是所谓的“预检”(read about it here)。基本上,如果请求是跨域的并且看起来“危险”(“安全”请求是GET / HEAD / POST,没有自定义标头和application/x-www-form-urlencoded / multipart/form-data / text/plain作为Content-Type),浏览器首先发送OPTIONS请求,以确保允许跨源请求。如果设置了正确的标题,它将发送实际的请求。

您正在尝试在app.all处理程序中设置正确的标头,但它们不在响应中。

首先,我们来看看如何表达处理请求。它首先运行附加到app的所有中间件(按照它附加的顺序)。 “中间件”是与app.use相关联的任何内容。然后,它按照它们所附的顺序经过每条路线。路由是与app.allapp.get等相关联的任何内容。如果这些步骤中的任何一个未能调用next(通常是因为他们发送了响应),则链将停止。

由于您的标头是在app.all中设置的,因此它们是路由阶段的一部分。由于您将routerapp.use相关联,因此它是中间件阶段的一部分。

但是,看到OPTIONS请求的快速路由器的URL与其中一条路由匹配会产生一些特殊情况。如果它在未完成请求的情况下到达该路由器的末尾,它会自动发送带有Allow标头集的响应。这就是为什么请求永远不会进入设置标头的app.all路由。

建议的修复:在中间件(OPTIONS)中设置标头(并在方法为app.use时发送响应),而不是路由。您还必须确保在处理/login的路由器之前连接此中间件。

因此,请使用app.all('/*',代替app.use('/',。确保在app.use('/', router)之前发生这种情况。