2014-10-29 72 views
3

我想在我的MEAN堆栈应用程序上进行Facebook授权。我正在使用passportpassport-facebook。我不使用jadeejs,我想使用纯粹的angularjs。当我运行我的应用程序,并单击按钮“登录”,我得到以下错误:MEAN堆栈Facebook授权错误:No'Access-Control-Allow-Origin'标头?

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

我做了一些研究,发现节点cors模块可以解决这个问题,但事实并非如此。

我做了什么错,我该如何解决?

这里是我的routes.js文件(服务器端):

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

app.get('/auth/facebook/callback', passport.authenticate('facebook', { 
    successRedirect: '/success', 
    failureRedirect: '/error' 
})); 

app.post('/success', function(req, res, next) { 
    User.findById(req.session.passport.user, function(err, user) { 
     if(err){ 
      res.send({success:false}); 
     }else{ 
      res.send({success:true,user: user}); 
     } 
    }); 
}); 

app.get('/logout', function(req, res){ 
    req.logout(); 
    res.redirect('/'); 
    res.end(); 
}); 

app.post('/error', function(req, res, next) { 
    res.send({success:false}); 
}); 

这里是我的passport.js文件(服务器端):
注:clientIDclientSectretcallbackURL是另一个文件(config.js)。但它们是有效的。

passport.use(new FacebookStrategy({ 
    clientID: config.facebookAuth.clientID, 
    clientSecret: config.facebookAuth.clientSecret, 
    callbackURL: config.facebookAuth.callbackURL 
    }, 
    function(accessToken, refreshToken, profile, done) { 
     User.findOne({ oauthID: profile.id }, function(err, user) { 
      if(err) { console.log(err); } 
      if (!err && user != null) { 
       done(null, user); 
      } else { 
       var user = new User({ 
        oauthID: profile.id, 
        name: profile.displayName, 
        created: Date.now() 
       }); 
       user.save(function(err) { 

        if(err) { 
         console.log(err); 
        } else { 
         console.log("saving user ..."); 
         done(null, user); 
        } 
       }); 
      } 
     }); 
    } 
)); 


// serialize and deserialize 
passport.serializeUser(function(user, done) { 
    console.log('serializeUser: ' + user._id) 
    done(null, user._id); 
}); 
passport.deserializeUser(function(id, done) { 
    User.findById(id, function(err, user){ 
     console.log(user) 
     if(!err) {done(null, user);} 
     else {done(err, null)} 
    }); 
}); 

这里是我的快递配置文件:express.js(服务器端):

var express = require('express'), 
    passport = require('passport'), 
    cookieParser = require('cookie-parser'), 
    bodyParser = require('body-parser'), 
    session = require('express-session'), 
    cors = require('cors'); 

var whitelist = ['https://www.facebook.com']; 
var corsOptions = { 
    origin: function(origin, callback){ 
    var originIsWhitelisted = whitelist.indexOf(origin) !== -1; 
    callback(null, originIsWhitelisted); 
    } 
}; 

module.exports = function (app, config) { 
    app.set('view engine', 'ejs'); 
    app.use(cookieParser()); 
    app.use(bodyParser()); 
    app.use(cors(corsOptions)); 
    app.use(session({secret:"car advisor secret"})); 
    app.use(passport.initialize()); 
    app.use(passport.session()); 
    app.use(express.static(config.rootPath+"/public")); 
} 

客户端

这里是我的html文件:

<body> 
    <div class="navbar-right" ng-controller="LoginCtrl"> 
     <form class="navbar-form" > 
      <a class="btn btn-primary" ng-click="signin()" ng-show="!identity.isAuthenticated()">Sign in</a> 
      <a class="btn btn-primary" ng-click="signout()" ng-show="identity.isAuthenticated()">Sign out | {{identity.currentUser.name}}</a> 
     </form> 
    </div> 
    <ng-view></ng-view> 

这里我的登录控制器:

$scope.signin = function(username, password) { 
    authService.authenticateUser(username, password).then(function(success) { 
     if (success){ 
      console.log("You have successfully signed in!"); 
     } 
    }); 
} 

$scope.signout = function() { 
    authService.logoutUser().then(function() { 
     console.log("You have successfully signed out!"); 
     $location.path('/'); 
    }); 
} 

这里是我的服务,处理的服务器通信(authService.js):

carApp.factory('authService', function($http, Identity, $q, $cookieStore, $resource) { 
return { 
    authenticateUser: function(username, password) { 
     var dfd = $q.defer(); 
     $http.get('/auth/facebook'). 
      success(function(data, status, headers, config) { 
       if (data.success) { 
        Identity.currentUser = response.data.user; 
        $cookieStore.put('user', response.data.user); 
        dfd.resolve(true); 
       } else { 
        $cookieStore.remove('user'); 
        dfd.resolve(false); 
       } 
      }); 
     return dfd.promise; 
    }, 
    logoutUser: function() { 
     var dfd = $q.defer(); 
     $http.get('/logout').success(function() { 
      Identity.currentUser = undefined; 
      $cookieStore.remove('user'); 
      dfd.resolve(); 
     }); 
     return dfd.promise; 
    } 
+0

我面临着类似的issue..did你得到了这个解决方案..?你能帮助我吗? – 2016-12-23 15:10:26

回答

0

你不能让一个Ajax请求到不同的地址。即使地址相同且端口不同,您也会遇到“相同的原产地策略”问题。

您可以使用nginx并使用proxy_pass重定向请求。

检查: http://distinctplace.com/infrastructure/2013/10/14/internal-redirect-to-another-domain-with-proxy_pass-and-nginx/

server 
{ 
    listen 80; 
    server_name localhost; 

    location /auth/facebook/request { 
    proxy_pass http://(...)facebook.com/(...); 
    } 
} 
+0

这个答案充其量是误导。 http://en.wikipedia.org/wiki/Cross-origin_resource_sharing – 2015-01-09 02:32:33

+0

我不会说误导,但不完整。是的,使用CORS你可以向不同的域请求,但它必须被服务器允许。我相信facebook API允许,但是如果OP使用其他可能没有Access-Control-Allow-Origin头的API,则会出现同样的问题。 现在使用Nginx的其他原因是,并非所有浏览器都完全支持此功能。 http://caniuse.com/#feat=cors – 2015-01-19 12:36:55

2

我不知道这样做是否解决您的问题,但我最近通过类似的事情去努力做一个Facebook帐号登录一个角度应用程序。请确保在您的Facebook应用程序设置页面中,

https://developers.facebook.com/apps/{your_app_id}/settings/ 

将“站点URL”更改为任何本地主机。例如:

http://localhost:8080/ 
+0

“网站网址”设置在哪里? – Matt 2018-02-13 15:12:04

+1

@Matt facebook UI发布后发生了很大变化,转到您的应用程序面板,选择左侧的“设置”,您将能够添加“域名”和“网站URL” – 2018-02-16 22:32:37

+0

谢谢,我会检查出来 – Matt 2018-02-17 10:00:05

1

你好,我不知道这是否帮助你尝试

app.config(['$httpProvider', function ($httpProvider){ 
     $httpProvider.defaults.useXDomain = true; 
    // $httpProvider.defaults.cache = true; 
     $httpProvider.defaults.withCredentials = true; 
    // $httpProvider.defaults.xsrfCookieName = ''; 
    // $httpProvider.defaults.xsrfHeaderName = ''; 
     delete $httpProvider.defaults.headers.common['X-Requested-With']; 
}]);