【问题标题】:Cross-Origin Request Blocked erroring out after adding application/json添加应用程序/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://stackoverflow.com/a/42965820/7055769

【问题讨论】:

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

标签: javascript node.js reactjs express cors


【解决方案1】:

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

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

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

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()); 参数的情况下中断。如果有人对此有更好的答案,和/或发现任何安全漏洞,请发表评论并告诉我。再次感谢大家的帮助!

    【讨论】:

      猜你喜欢
      • 2021-08-30
      • 2021-06-26
      • 2014-10-13
      • 2015-06-08
      • 2015-05-05
      • 2019-11-04
      • 2017-02-06
      相关资源
      最近更新 更多