Angular/Node/Express/Passport 跨域问题 - 启用 CORS Passport Facebook 身份验证

Posted

技术标签:

【中文标题】Angular/Node/Express/Passport 跨域问题 - 启用 CORS Passport Facebook 身份验证【英文标题】:Angular/Node/Express/Passport Cross Domain Problems - Enable CORS Passport Facebook Authentication 【发布时间】:2014-11-19 16:45:06 【问题描述】:

在 NodeJS/Express 中尝试使用 Passport 对 Facebook 用户进行身份验证时,已有 100 万人尝试启用 CORS。

我在 Chrome 上遇到的错误是这样的:

XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%…%3A8080%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=598171076960591. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:8080' is therefore not allowed access. 

我使用的路线就这么简单:

// =====================================
// FACEBOOK ROUTES =====================
// =====================================
// route for facebook authentication and login

app.get('/auth/facebook', passport.authenticate('facebook',  scope : 'email' ));

// handle the callback after facebook has authenticated the user
app.get('/auth/facebook/callback',
    passport.authenticate('facebook', 
        successRedirect : '/home',
        failureRedirect : '/login'
    ));

这是在我的 angularJS 文件上调用路由的方式(我也尝试过设置 withCredentials : true):

$http.get('/auth/facebook')
    .success(function(response) 

    ).error(function(response)

    );

我尝试了十几种解决方案,这些解决方案是在 *** 和其他论坛上找到的。

    我尝试在 routes.js 文件的路由之前添加此内容:

    app.all('*', function(req, res, next) 
      res.header('Access-Control-Allow-Origin', '*');
      res.header("Access-Control-Allow-Headers", "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name");
      res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
      res.header('Access-Control-Allow-Credentials', true);
    
      if ('OPTIONS' == req.method) 
          res.send(200);
       else 
          next();
      
    );
    

    我尝试在 server.js 文件中添加它(请注意,我将 header 更改为 setHeader,但我都尝试过):

    app.use(function(req, res, next) 
      res.setHeader('Access-Control-Allow-Origin', '*');
      res.setHeader('Access-Control-Allow-Headers', 'Content-Type,X-Requested-With');
      res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
      res.setHeader('Access-Control-Allow-Credentials', true);
    
      if ('OPTIONS' == req.method) 
        res.send(200);
       else 
        next();
      
    
     );
    
     require('./app/routes.js')(app, passport);
    

    我尝试在我的 app.js 文件中添加这个(angularJS 配置):

    $httpProvider.defaults.useXDomain = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
    $httpProvider.defaults.withCredentials = true;
    

不管怎样,我不知道还能做什么。我在网上找到的所有东西都不起作用。 是否有可能与我使用 AngularJS 路由有关?我看不出这有什么重要的原因,但我有点猜不透了。

我的情况和这个很相似: Angular/Node/Express/Passport - Issues when connecting to facebook(CORS)

提前致谢!

【问题讨论】:

How to allow CORS in Express/NodeJS?的可能重复 我知道有很多类似的问题,而且我几乎都看过。不幸的是,到目前为止,我尝试过的解决方案都没有奏效...... 您不能同时使用Access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *'。对于您的情况,您应该设置 Access-Control-Allow-Origin: localhost:8080 而不是 * 嗨@LarissaLeite,你有没有让这个与anguar一起工作?我现在正在尝试,但遇到了您的问题。 @LarissaLeite 你找到解决方案了吗?你发布这个已经两年了,但我现在面临这个问题。谢谢 【参考方案1】:

Facebook 登录和 cors 也有问题,但 NodeJS/Express 中的 Passport 没有, 我的应用程序是 java(spring mvc)+ angular。我已经设法解决了修改我的初始 fb 登录功能的问题:

$scope.loginWithFacebook = function () 
    $http(
        method: 'GET',
        url: 'auth/facebook',
        dataType: 'jsonp'
    ).success(function(data)
        console.log('loginWithFacebook success: ', data);
    ).error(function(data, status, headers, config) 
        console.log('loginWithFacebook error: ', data);
    );

$scope.loginWithFacebook = function() 
    $window.location = $window.location.protocol + "//" + $window.location.host + $window.location.pathname + "auth/facebook";
;

希望对你有帮助!

【讨论】:

@mikestaub 您无法调用服务器 api,这将导致前端出现 302(重定向),因此您必须将用户直接发送到服务器 如果您正在模拟 href 点击或 http 重定向到另一个域,这如何帮助找出提供商(fb、google)的响应?【参考方案2】:

我遇到了这个问题,几乎到了我确信我找不到解决方案的地步,但是再次查看一个简单的教程 (http://mherman.org/blog/2013/11/10/social-authentication-with-passport-dot-js/) 为我解决了这个问题。我试图从 Angular 到 Node.js 进行 API 调用,不管你在服务器上配置了什么,无论是否有 CORS,它总是会给你带来那些 XMLHttpRequest 错误! CORS 不是固定装置 - 如果您打开 Chrome 网络控制台,您会发现您对 Google 或 Facebook 或任何第三方网站的请求是您无法控制的 - 它是由发送回的 302 重定向触发的您的前端,Angular.js 或任何其他框架都无法控制的东西,因此无论如何您都不能真正将“访问控制允许来源”添加到该请求中。

解决方案只是将“使用_____ 登录”的按钮或文本设为链接。文字 <a href="/auth/facebook"></a> 链接。就是这样。

当然,在这个过程中我也遇到了很多其他的绊脚石和陷阱。我尝试不使用 passport.authenticate('facebook') 的默认中间件,但尝试将其包装在 function(req, res, next) ... 中,认为这会有所作为,但事实并非如此。

【讨论】:

我正在使用 UI-Router。我尝试了该链接,但被$urlRouterProvider.otherwise('/'); 捕获并将我带到我的主页。有什么想法吗? @AdamZerner,这仅仅是因为您尝试的链接不是有效的“前端 URL”(或者说不是角度路由器识别的 URL),这就是 $urlRouterProvider.otherwise('/');解决方法其实很简单,你只需要在 a 标签中添加 'target="_self" ',它会绕过 Angular 路由器。 嘿,我被困在与原始问题完全相同的问题上。 Gary 的回答和 Spiritwalker 的评论相结合,修复了与 CORS 错误和重定向相关的所有问题。工作就像一个魅力。谢谢@Gary和spiritwalker。 如何将用户对象或令牌发送回前端? @Moody 它肯定适用于 localstrategy,但我不确定 facebook,因为自从我离开项目后他们改变了它。 pastebin.com/svuubYDApastebin.com/gR8e14SX/?e=1pastebin.com/RJdp4j5q【参考方案3】:

创建一个 html 标签来执行 GET 请求,facebook 不允许 XMLHttpsRequests。

像这样: <a href="http://localhost:8080/auth/facebook">sign in with facebook</a>

【讨论】:

以上是关于Angular/Node/Express/Passport 跨域问题 - 启用 CORS Passport Facebook 身份验证的主要内容,如果未能解决你的问题,请参考以下文章