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: true
和Access-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 身份验证的主要内容,如果未能解决你的问题,请参考以下文章