Access to XMLHttpRequest at 'http://localhost:8080/api/user/login' from origin 'http://localhost:808

用nodejs+express封装自己的api,遇到跨域问题

原本我是这样写进去的:

//设置跨域访问
app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

后来浏览器一直:

 

解决方式:

 把上边的第二句换成:

    res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');

完整代码:

var express = require('express');
var md5 = require('js-md5');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json({
  limit: '1mb'
}));
app.use(bodyParser.urlencoded({
  limit: '1mb',
  extended: true
}));
var DatabaseOperation = require('./connection');

//引用bodyParser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
//设置跨域请求
app.all('*', function (req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  res.header("X-Powered-By", ' 3.2.1')
  res.header("Content-Type", "application/json;charset=utf-8");
  next();
});

//用户注册
app.get('/api/user/register', function (req, res) {
  DatabaseOperation.select('user', {
    "username": req.query.username,
  }, function (result) {
    if (result.length > 0) {
      result = {
        code: '1001'
      }
      res.json(result);
    } else {
      DatabaseOperation.insert('user', [{
        "username": req.query.username,
        "password": md5(req.query.password)
      }], function (result) {
        res.json(result)
      });
    }
  });
});

const port = 8080;
app.listen(port, () => {
  console.log('Express server listening on port ' + port);
});

connection.js

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
var dataconfig = require('./dataconfig');
var DatabaseOperation = {
  /*
  @selectall 方法返回全部所有数据
  @dataname 数据库名称
  @dealdata 回调处理函数 格式function(result){};
  */
  selectall: function (dataname, dealdata) {
    const client = new MongoClient(dataconfig.dataurl);
    client.connect(function (err) {
      assert.equal(null, err);
      console.log("数据库连接成功");
      const db = client.db(dataconfig.dataname);
      db.collection(dataname).find({}).toArray(function (err, result) { // 返回集合中所有数据
        if (err) throw err;
        dealdata(result);
      });
      client.close();
    })
  },
  /*
  @selectone 查询符合条件的数据
  @dataname 数据库名称
  @selectlanguage 查询控制语句 格式{index:value,index,value};
  @dealdata 回调处理函数 格式function(result){};
  */
  select: function (dataname, selectlanguage, dealdata) {
    const client = new MongoClient(dataconfig.dataurl);
    client.connect(function (err) {
      assert.equal(null, err);
      console.log("数据库连接成功");
      const db = client.db(dataconfig.dataname);
      db.collection(dataname).find(selectlanguage).toArray(function (err, docs) {
        console.log('find');
        dealdata(docs);
        client.close();
      });
    })
  },
  /*
  @insert添加数据格式json格式
  @dataname 数据库名称
  @dealdata 回调函数处理函数有一个result参数
  */
  insert: function (dataname, insertlanguage, dealdata) {
    const client = new MongoClient(dataconfig.dataurl);
    client.connect(function (err) {
      assert.equal(null, err);
      console.log("数据库连接成功");
      const db = client.db(dataconfig.dataname);
      db.collection(dataname).insertMany(insertlanguage, function (err, result) {
        assert.equal(err, null);
        dealdata(result);
        client.close();
      });
    })
  },
  /*
@update 修改数据的方法
@update添加数据格式json格式
@dataname 数据库名称
@dealdata 回调函数处理函数有一个result参数
*/
  update: function (dataname, updatelanguage, updatecondition, dealdata) {
    const client = new MongoClient(dataconfig.dataurl);
    client.connect(function (err) {
      assert.equal(null, err);
      console.log("数据库连接成功");
      const db = client.db(dataconfig.dataname);
      db.collection(dataname).updateOne(updatelanguage, updatecondition, function (err, result) {
        assert.equal(err, null);
        dealdata(result);
        client.close();
      });
    })
  },
  /*
  @removeall 删除数据的方法
  @dataname 数据库名称
  @removelanguage 删除数据的条件
  @dealdata 回调函数处理函数有一个result参数
  */
  removeall: function (dataname, removelanguage, dealdata) {
    const client = new MongoClient(dataconfig.dataurl);
    client.connect(function (err) {
      assert.equal(null, err);
      const db = client.db(dataconfig.dataname);
      db.collection(dataname).findAndRemove(removelanguage, function (err, result) {
        assert.equal(err, null);
        dealdata(result);
        client.close();
      });
    })
  },

};

// 测试用例
// DatabaseOperation.selectall('address', function(result) {
//         console.log("select查询结果");
//         console.log(result);
//     })
// DatabaseOperation.select('address', {
//     "addressid": "2"
// }, function(result) {
//     console.log("select查询结果");
//     console.log(result);
// });
// DatabaseOperation.insert('address', [{
//         "insert": "hello"
//     }], function(result) {
//         console.log('inserts插入结果');
//         console.log(result);
//     })
// DatabaseOperation.removeall('note', {
//     "id": "5ce177b965ee630c046266af"
// }, function(result) {
//     console.log(result);
// })

module.exports = DatabaseOperation;

 

最后愉快地解决了!

接下来了解一下响应头是什么(只说明上边的几个,其他自行了解):

上边的设置,在前端请求后端接口的时候,就会用到:

 

Access-Control-Allow-Headers:Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild :响应首部,用于预检请求中,代表将会在正式请求的Access-Control-Expose-Headers 字段中出现的首部信息。

其中:

Content-Type: 实体头部用于指示资源的MIME类型 media type 。

在响应中,Content-Type标头告诉客户端实际返回的内容的内容类型。浏览器会在某些情况下进行MIME查找,并不一定遵循此标题的值; 为了防止这种行为,可以将标题 X-Content-Type-Options 设置为 nosnif

Authorization :请求头含有服务器用于验证用户代理身份的凭证。

Accept :请求头用来告知客户端可以处理的内容类型

Access-Control-Allow-Origin:* : 响应头指定了该响应的资源是否被允许与给定的origin共享,对于不需具备凭证(credentials)的请求,服务器会以“*”作为通配符,从而允许所有域都具有访问资源的权限。或者也可以指定进行限制

Content-Length :74 : 表明了实体主体部分的大小(单位是字节)

Access-Control-Allow-Methods:PUT,POST,GET,DELETE,OPTIONS:服务器端允许的请求方式,常用get、post

Date: 其中包含了报文创建的日期和时间。格式:

Date: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT

<day-name>

"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 或 "Sun" 之一 (区分大小写)。

<day>

2位数字表示天数,例如, "04" 或 "23"。

<month>

"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 之一(区分大小写)。

<year>

4位数字表示年份,例如, "1990" 或 "2016"。

<hour>

2位数字表示小时数,例如, "09" 或 "23"。

<minute>

2位数字表示分钟数,例如, "04" 或 "59"。

<second>

2位数字表示秒数,例如, "04" 或 "59"。

GMT

格林尼治标准时间。 在HTTP协议中,时间都是用格林尼治标准时间来表示的,而不是本地时间。

Content-Type:application/json; charset=utf-8: 说明实体内对象的媒体类型。

HTTP响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web服务器不需要发送完整的响应。而如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖(“空中碰撞”)。

ETag:如果给定URL中的资源更改,则一定要生成新的Etag值。 因此Etags类似于指纹,也可能被某些服务器用于跟踪。 比较etags能快速确定此资源是否变化,但也可能被跟踪服务器永久存留。

X-Powered-By: 3.2.1 : 这个查了半天没找到一个合理的解释,出于安全考虑一般会隐藏,不过使用express会自动暴露,于是就手动修改:

默认:

默认暴露我们使用的框架是express

这样隐藏掉:

 res.header("X-Powered-By", ' 3.2.1')

想了解更多精彩的你:

 

 

 

 

 

 

 

 

 

回答: 根据提供的引用内容,http://localhost:8080/#/ 是一个网址,它是用来访问部署在Tomcat服务器上的项目的。在部署项目之前,需要先修改配置并保存,然后将项目部署到Tomcat安装目录下的webapp文件夹中。接着重启Tomcat服务器,就可以通过访问http://localhost:8080来正常访问项目了。\[1\]然而,有时候在前后端分离的情况下,当Vue调用SpringBoot方法时,可能会出现跨域错误。这是因为浏览器的同源策略限制了浏览器执行其他网站的脚本。解决这个问题可以通过在后端添加'Access-Control-Allow-Origin'头来允许跨域访问。\[2\]此外,如果在浏览器输入http://localhost:8080之前没有启动Tomcat服务器,那么页面将无法打开。因此,在访问该网址之前,确保Tomcat服务器已经启动并且保持运行状态。\[3\] #### 引用[.reference_title] - *1* *3* [Tomat安装之后http://localhost:8080无法访问最全解决方案](https://blog.csdn.net/vagatable_XX/article/details/121580764)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [跨域Access to XMLHttpRequest at ‘http://localhost:8181/list‘ from originhttp://localhost:8080...](https://blog.csdn.net/weixin_43768573/article/details/128367108)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值