Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 使用MEAN stack应用程序消除CORS策略错误(托管在Heroku上)_Node.js_Angular_Typescript_Express_Cors - Fatal编程技术网

Node.js 使用MEAN stack应用程序消除CORS策略错误(托管在Heroku上)

Node.js 使用MEAN stack应用程序消除CORS策略错误(托管在Heroku上),node.js,angular,typescript,express,cors,Node.js,Angular,Typescript,Express,Cors,我在一个MEAN stack应用程序上工作了一段时间,在过去的一个月里,我一直在努力解决这个CORS策略错误: “从源站访问XMLHTTPRequest已被CORS策略阻止:对飞行前请求的响应未通过访问控制检查:'访问控制允许源站'的值不等于提供的源站。” 我已经在一些设备上取得了一些成功。在我的server.js文件中的中间件函数中的请求/响应头设置和在与后端通信的服务中发布请求后,我已经让它在我的桌面(Windows 10)、我的桌面上的Ubuntu操作系统、我的笔记本电脑(Windows

我在一个MEAN stack应用程序上工作了一段时间,在过去的一个月里,我一直在努力解决这个CORS策略错误:

“从源站访问XMLHTTPRequest已被CORS策略阻止:对飞行前请求的响应未通过访问控制检查:'访问控制允许源站'的值不等于提供的源站。”

我已经在一些设备上取得了一些成功。在我的server.js文件中的中间件函数中的请求/响应头设置和在与后端通信的服务中发布请求后,我已经让它在我的桌面(Windows 10)、我的桌面上的Ubuntu操作系统、我的笔记本电脑(Windows 10)、我的朋友macbook等上工作

然而,我仍然在我朋友的一些设备上遇到CORS策略问题。什么设备工作和什么设备不工作似乎没有任何共同之处(不同的操作系统工作和不工作,当它不工作时,它跨所有浏览器)

可能还值得注意的是,在出现CORS错误的设备上,我的应用程序页面右上角显示“不安全”,而在它工作的设备上,则标记为安全

我做过的事情:

  • 已在my server.js文件中导入cors模块
  • 尝试使用csp(内容安全策略)模块
  • 修改了发送到我的服务器的请求的标题
  • 修改了从服务器发送回客户端的响应的标题
  • 大量的谷歌搜索和摆弄CORS策略设置
如果相关的话,我还使用passport和bcrypt进行用户身份验证

以下是相关的server.js代码:

var express = require('express');
var cors = require('cors');
//var csp = require('content-security-policy');
var app = express();
var dotenv = require('dotenv');
dotenv.config();

var url = require('url');

var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session'); // should give us persistent sessions...
var passport = require('passport');
var ejs = require('ejs');
var bcrypt = require('bcrypt');
var flash = require('express-flash');
var mongoose = require('mongoose');
var path = require('path');
//const env = require('./src/environments/environment');
//const methodOverride = require('method-override')
//var initializePassport = require('passport-config');
var initializePassport = require('./passport-config');
// this completes passport authentication strategy
// passes passport, a function for finding a user by their username,
// and a function for finding a user by id to the initialize() function inside passport-config
// the authenticateUser function then uses these methods to get what it needs
var connurl = '';
if(process.env.NODE_ENV == 'development'){
  connurl = 'http://localhost:4200';
}
else{
  connurl = 'https://to-do-bentancock.herokuapp.com';
}

initializePassport(
  passport,
  // both of these things are functions, passed into passport config
  // I think I pass mongoose middleware stuff here to return the right things
  username => Users.find({username: { $eq: username }}),
  id => Users.find({id: { $eq: id }})
)

var MongoStore = require('connect-mongo')(session);
var router = express.Router();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser('process.env.SECRET'));

var cspPolicy = {
  'default-src': 'self, https://to-do-bentancock.herokuapp.com/*',
  'img-src': '*',
}

/*app.use(csp({
  policies: {
    'default-src': [csp.NONE],
    'img-src': [csp.SELF],
  }
}));

const globalCSP = csp.getCSP(cspPolicy);
app.use(globalCSP)

*/

app.use(session({
  secret: 'process.env.SECRET',
  resave: true, // should we reset our session variables if nothing has changed?
  // NOTE: this MUST be set to true otherwise the user authentication / session data won't be saved between middleware methods
  // e.g. if you log in (via /tasks post method), it will print the session data at the end, but if you then do '/create' method right after the req object will be null (because it wasn't saved)
  saveUninitialized: true, // do you want to save an empty value in the session if there is no value?
  cookie: {
    // might want to look into changing this in the future, as cookie stores user stuff
    // for now I have it off until I'm certain I've got all this passport js, cookie and session stuff down pat
    secure: false,
    maxAge: 600000
  },
  store: new MongoStore({
    mongooseConnection: mongoose.connection,
    ttl: 60 * 60, // keeps the session open for 1 hour
    collection: 'sessions'
  })
}));

app.use(passport.initialize());
app.use(passport.session());

app.use(cors({credentials: true, origin: true}));

// enables pre-flight requests across the board
app.options('*', cors()) // include before other routes

app.get('/with-cors', cors(), (req, res, next) => {
  console.log("testing cors:");
});

app.use('/', express.query());

app.get('/*', function(req,res) {
  res.header("Access-Control-Allow-Origin", connurl);
  res.header('Access-Control-Allow-Credentials', true);
  //res.header('Content-Type', 'application/json');
  console.log("here's what app.get is receiving: " + req.url);
  console.log("sending file!");
  res.sendFile(path.join(__dirname + '/dist/to-do-heroku/index.html'));
});

app.post('/loginCheck', function(req, res){
  res.header("Access-Control-Allow-Origin", connurl);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Content-Type', 'application/json');

  console.log("res header: %j", res.getHeaders());
  console.log("\nlogin check");
  if(req.isAuthenticated()){
    console.log("authentication returns true!");
    //console.log("printing req passport data: ");
    //console.log(req.session);
    //console.log(req.user);
    //res.headersSent();
    res.send({authenticated: true});
  }
  else{
    console.log("user is not authenticated");
    res.send({authenticated: false});
  }
});

app.post('/login', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", connurl);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Content-Type', 'application/json');
  console.log("res header: %j", res.getHeaders());
  passport.authenticate('local', function(err, user, info) {
    console.log("printing error: " + err);
    console.log("passport info: " + JSON.stringify(info)); // undefined
    if(err){
      console.log("error authenticating!");
      res.send({status: 'error logging in user'});
      return;
    }

    if(!err){
      req.logIn(user, function(err){
        if(err){
          console.log("error logging in");
          //return
        }
        res.send({status: 'success'});
      });
    }
  })(req, res, next);
});

app.post('/logout', checkAuthenticated, async function(req, res){
  res.header("Access-Control-Allow-Origin", connurl);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Content-Type', 'application/json');
  console.log("\nlogging out user");
  await req.logout(); // logOut or logout??
  res.send({status: 'redirect', url: '/login'});
});


app.post('/getTasks', checkAuthenticated, function(req, res){
    res.header("Access-Control-Allow-Origin", connurl);
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Content-Type', 'application/json');
    console.log("\n Successful authentication, request: " + JSON.stringify(req.body));

    Users.find({id: { $eq: req.session.passport.user}}, function(err, doc){
      if(!doc.length || doc == null){ // if the user is not found
        console.log("ERROR: USER NOT FOUND, LOGGING OUT");
        req.logOut();
        res.send({error:'not found'}); // send some kind of message back to client-side
      }
      else{
        res.send({tasks: doc[0].tasks, idCount: doc[0].idCount});
      }

    });
});



var uri = '';
if(process.env.NODE_ENV == 'development'){
  uri = 'mongodb://localhost/todoDB'
}
else{
  uri = "mongodb+srv://todoApp:7211@cluster0.huawl.mongodb.net/toDoDB?retryWrites=true&w=majority";
}


//const uri = "mongodb+srv://todoApp:7211@cluster0.huawl.mongodb.net/toDoDB?retryWrites=true&w=majority";
mongoose.connect(uri);
const connection = mongoose.connection;
connection.once('open', function(){
  mongoose.connection.db.collection('usersCollection').countDocuments(function(err, docs){
    console.log("there are " + docs + " docs in the collection\n");
  });
  console.log("MongoDB database connection established successfully\n");
});

function checkAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    console.log("user is authenticated!");
    return next();
  }
  console.log("WARNING: USER NOT AUTHENTICATED");
  res.send({authenticated: false});
}

function checkNotAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    console.log("\nuser IS authenticated, stopping this request...");
    // Send a message back to the client telling it to redirect instead
    //res.send({authenticated: true});
    return;
  }
  //res.send({authenticated: false});
  console.log("user is NOT authenticated");
  next();
}



if(process.env.NODE_ENV == 'development'){
  app.listen(4000, function(req, res){
    console.log("express server listening on port 4000");
  });
}
else{
  app.listen(process.env.PORT || 8080, function(req, res){
    console.log("express server listening on port 8080");
  });

}


下面是与server.js通信的服务的代码:

身份验证服务:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { Subject } from 'rxjs';
import { environment } from './../environments/environment';


@Injectable({
  providedIn: 'root'
})
export class AuthService {

  url = environment.apiUrl;


  username;
  password;
  loggedIn = false;



  constructor(private http: HttpClient, private router: Router) { }

  login(uname, pw){
    console.log("logging in user: " + uname + " " + pw + '\n');
    console.log("the url: " + this.url);
    this.username = uname;
    this.password = pw;
    return this.http.post(this.url + '/login', {username: uname, password: pw}, {
      headers: new HttpHeaders({
        'Access-Control-Allow-Credentials' : 'true',
        'Access-Control-Allow-Origin': "*" // this might just need to be the api url
      }),
      withCredentials: true
    });
  }

  setLogin(bool){
    this.loggedIn = bool;
  }

  logout(){
    console.log("test auth logout");
    return this.http.post(this.url + '/logout', {body: 'logout'},  {
      headers: new HttpHeaders({
        'Content-Type' : 'application/json',
        'Access-Control-Allow-Credentials' : 'true',
        'Access-Control-Allow-Origin': "*"
      }),
      withCredentials: true
    });
  }

  loginCheck(){
    console.log("test auth service login check");
    return this.http.post(this.url + '/loginCheck', {
      headers: new HttpHeaders({
        'Content-Type' : 'application/json',
        'Access-Control-Allow-Credentials' : 'true',
        'Access-Control-Allow-Origin': "*"
      }),
      withCredentials: true
    });
  }


  registerUser(uname, pw){
    console.log("registering user: " + uname + " " + pw + '\n');

    // the object sent needs to be a user object, which contains task objects
    // new user won't have any tasks tho (obvi)
    // also need to check for duplicate usernames
    return this.http.post(this.url + '/register',
    {
      username: uname,
      password: pw,
      idCount: 0,
      id: Date.now().toString(),
      tasks: []
    },
    {
      headers: new HttpHeaders({
        'Content-Type' : 'application/json',
        'Access-Control-Allow-Credentials' : 'true',
        'Access-Control-Allow-Origin': "*"
      }),
      withCredentials: true
    });
  }


  // takes user tasks data as input, passes it to tasks component
  renderTasks(){
    console.log("render tasks \n");
    this.router.navigate(['/tasks']);
  }

任务.服务:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { catchError, tap, share, map } from 'rxjs/operators';
import { environment } from './../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class TasksService {
  //url = 'http://localhost:4000' // the port the mongo database is listening on
  //url = 'https://to-do-bentancock.herokuapp.com';
  url = environment.apiUrl;
  constructor(private http: HttpClient) { }


  getTasks(userName, pw){
    console.log("tasks service: get tasks \n");
    console.log("username and pw to post: " + userName + " " + pw);

    return this.http.post(this.url + '/getTasks', {username: userName, password: pw},
    {
      headers: new HttpHeaders({
        'Content-Type' : 'application/json',
        'Access-Control-Allow-Credentials' : 'true',
        'Access-Control-Allow-Origin': "*"
      }),
      withCredentials: true
    });
  }

  deleteTask(uname, pw, id: number ){
    var delUrl = this.url + "/deleteTask/" + id;

    return this.http.post(delUrl, {username: uname, password: pw},
      {
        headers: new HttpHeaders({
          'Content-Type' : 'application/json',
          'Access-Control-Allow-Credentials' : 'true',
          'Access-Control-Allow-Origin': "*"
        }),
        withCredentials: true
      }
    );

  }

  /*
  a task object has a:
  - name
  - date
  - description
  - priority
  - id
  */
  createTask(uname, pw, task){
    console.log("test create task (service)");

    // send user data, and a task object
    return this.http.post(this.url + '/create',
    {
      task:
      {
        name: task.name,
        date: task.date,
        description: task.description,
        priority: task.priority,
        id: task.id,
        state: task.state
      },
      user:
      {
        username: uname,
        password: pw
      }
    },
    {
      headers: new HttpHeaders({
        'Content-Type' : 'application/json',
        'Access-Control-Allow-Credentials' : 'true',
        'Access-Control-Allow-Origin': "*"
      }),
      withCredentials: true
    }
  );
  }

我一直在用谷歌搜索并解决这个问题,我已经筋疲力尽了。有人有什么建议吗?我遗漏了什么?

我只是在使用
app。在get中使用(cors())
而不使用
app.options('*',cors())
cors()