添加应用程序/json 后,跨域请求被阻止出错

Posted

技术标签:

【中文标题】添加应用程序/json 后,跨域请求被阻止出错【英文标题】:Cross-Origin Request Blocked erroring out after adding application/json 【发布时间】:2018-11-30 20:25:00 【问题描述】:

我正在尝试使用 React 向 Node 发送一些数据。这是我的反应代码:

sendMail(e) 
    e.preventDefault();
    // fetch('/https://uczsieapp-mailer.herokuapp.com/', 
    var name = document.getElementById('name').value;
    var contactReason = document.getElementById('contactReason').value;
    var email = document.getElementById('email').value;
    var additionalInfo = document.getElementById('additionalInfo').value;
    var body = 
        name: name,
        contactReason: contactReason,
        email: email,
        additionalInfo: additionalInfo,
    ;
    body = JSON.stringify(body);
    console.log(body);
    fetch('http://localhost:4000/', 
        method: 'POST',
        headers: 
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        ,
        content: body,
    ).then(r => console.log(r)).catch(e => console.log(e));

这是我的节点代码:

var cors = require('cors');
var app = express();
app.use(cors());
var a = '=';
router.post('/', (req, res, next) => 
        console.log('mailing');
        console.log(a);
        a += '=';
        var nodemailer = require('nodemailer');

        var transporter = nodemailer.createTransport(
            host: "smtp.gmail.com", // hostname
            auth: 
                user: 'someuser@gmail.com',
                pass: 'testgmail'
            
        );
        console.log(req.body.content);
        let mailOptions = 
            from: `$req.body.name $req.body.email`, // sender address
            to: 'alexander.ironside@mygeorgian.ca', // list of receivers
            subject: 'Email from UczSieApp contact form', // Subject line
            text: 'Hello world ', // plaintext body
            html: `
                    <h4>Imie: $req.body.name</h4>
                    <h4>Email: $req.body.email</h4>
                    <h4>Powod kontaktu: $req.body.contactReason</h4>
                    <p>Wiadomosc: $req.body.additionalInfo</p>
                    `
        ;

        // send mail with defined transport object
        transporter.sendMail(mailOptions, function (error, info) 
            if (error) 
                return console.log(error);
            

            console.log('Message sent: ' + info.response);
        );
    
);

如您所见,我正在使用cors module,它应该可以处理所有cors 问题。

但这还不够。当我摆脱传递给fetch()headers 属性时,调用正在完成,但没有发送数据。当我添加headers 时,我得到了乐趣

跨域请求被阻止:同源策略不允许读取位于http://localhost:4000/ 的远程资源。 (原因:CORS 标头“Access-Control-Allow-Origin”缺失)。

又报错了。

我怎样才能绕过它,我错过了什么?

我在编写代码时使用了这个答案:https://***.com/a/42965820/7055769

【问题讨论】:

CORS 是出于安全原因,考虑到 cors 代码(希望)不会部署到生产环境中,我认为采用另一种方法要好得多,例如安装 nginx(或apache,或码头或任何其他可以反向代理您的呼叫的服务器)本地并将您的呼叫从前端服务器代理到快速服务器。 我只想从网站发送一封电子邮件。该数据库基于 Firebase,因此 Node 将无法连接到数据库。 CORS 发生在客户端(您的反应应用程序)和服务器(您的快递)之间。您想根据我在您的代码中看到的内容从服务器发送电子邮件,所以我的建议仍然适用。 【参考方案1】:

事实证明,CORS 只允许某些特定的内容类型。

Content-Type 标头的唯一允许值是:

    application/x-www-form-urlencoded 多部分/表单数据 文本/纯文本

origin 参数指定一个可以访问资源的 URI。浏览器必须强制执行此操作。对于没有凭据的请求,服务器可以将“*”指定为通配符,从而允许任何来源访问资源。

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

fetch('http://localhost:4000/', 
    method: 'POST',
    mode: 'cors',
    headers: 
        'Access-Control-Allow-Origin': '*',
        'Accept': 'application/json',
        'Content-Type': 'application/json',
    ,
    content: body,
).then(response => response.json()).then(r => console.log(r)).catch(e => console.log(e));

【讨论】:

如果只允许3种类型,我不应该改变Content-Type的类型吗? Access-Control-Allow-Origin 设置在服务器的响应上,让浏览器知道哪些域可以访问它。在请求上设置它不会做任何事情。 javascript 无法绕过 CORS。如果可以,那将是一个毫无意义的安全机制。此标头必须由服务器在响应中设置。 @Taplar 但是服务器没有发送任何响应【参考方案2】:

您介意按以下方式尝试,这应该可以解决问题:

app.use(function (req, res, next) 
    //set headers to allow cross origin requestt
    res.header("Access-Control-Allow-Origin", "*");
    res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
); 

【讨论】:

【参考方案3】:

好的,有很多原因这不起作用。我将这个答案留给未来的开发者以减轻他们的痛苦。

这是在客户端工作的方法:

$.ajax(
    type: "POST",
    url: 'http://localhost:4000/',
    data: body,
    success: data=>console.log(data),
    dataType: 'json',
);

这是我的整个服务器端代码:

var express = require('express');
var router = express.Router();
var cors = require('cors');
var app = express();

app.use(cors());
app.options('*', cors());

var a = '=';
router.post('/', (req, res, next) => 
        console.log('mailing');
        console.log(a);
        a += '=';
        var nodemailer = require('nodemailer');

        var transporter = nodemailer.createTransport(
            host: "smtp.gmail.com", // hostname
            auth: 
                user: 'sqtableknights@gmail.com',
                pass: 'testgmail'
            
        );
        console.log(req.body);
        let mailOptions = 
            from: `$req.body.name $req.body.email`, // sender address
            to: 'alexander.ironside@mygeorgian.ca', // list of receivers
            subject: 'Email from UczSieApp contact form', // Subject line
            text: 'Hello world ', // plaintext body
            html: `
                        <h4>Imie: $req.body.name</h4>
                        <h4>Email: $req.body.email</h4>
                        <h4>Powod kontaktu: $req.body.contactReason</h4>
                        <p>Wiadomosc: $req.body.additionalInfo</p>
                        `
        ;

        // send mail with defined transport object
        transporter.sendMail(mailOptions, function (error, info) 
            if (error) 
                return console.log(error);
            

            console.log('Message sent: ' + info.response);
        );
    
);
module.exports = router;

所以在我的情况下,我必须添加这些:

app.use(cors());
app.options('*', cors());

不知道为什么,但它只是在没有app.options('*', cors()); 参数的情况下中断。如果有人对此有更好的答案,和/或发现任何安全漏洞,请发表评论并告诉我。再次感谢大家的帮助!

【讨论】:

以上是关于添加应用程序/json 后,跨域请求被阻止出错的主要内容,如果未能解决你的问题,请参考以下文章

跨域请求被阻止 Symfony/AngularJS

Autodesk Forge 跨域请求被阻止错误

跨域请求在 Firefox 中被阻止

Django之跨域请求

跨域请求被阻止:同源策略不允许在 http://localhost3000 读取远程资源

跨域请求被阻止原因:CORS 预检通道未成功