【问题标题】:MEAN stack Facebook authorization error: No 'Access-Control-Allow-Origin' header?MEAN stack Facebook 授权错误:没有“Access-Control-Allow-Origin”标头?
【发布时间】:2014-12-25 13:08:24
【问题描述】:

我正在尝试对我的 MEAN 堆栈应用程序进行 facebook 授权。我正在使用passportpassport-facebook。我没有使用jadeejs,我想使用纯angularjs。当我运行我的应用程序并单击“登录”按钮时,我收到以下错误:

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.

我做了一些研究,发现 node 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;
    }

【问题讨论】:

  • 我面临着类似的问题..你有解决方案吗..?你能帮我吗

标签: javascript facebook angularjs node.js express


【解决方案1】:

您不能向其他地址发出 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/(...);
  }
}

【讨论】:

  • 这个答案充其量是误导。 en.wikipedia.org/wiki/Cross-origin_resource_sharing
  • 我不会说误导,而是说不完整。是的,使用 CORS,您可以向不同的域发出请求,但必须得到服务器的允许。我相信 facebook API 允许,但如果 OP 使用可能没有 Access-Control-Allow-Origin 标头的其他 API,则会出现相同的问题。目前,使用 Nginx 的另一个原因是并非所有浏览器都完全支持此功能。 caniuse.com/#feat=cors
【解决方案2】:

我不确定这是否能解决您的问题,但我最近经历了类似的尝试,试图让一个 facebook 登录一个 Angular 应用程序。确保在您的 Facebook 应用设置页面中,

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

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

http://localhost:8080/

【讨论】:

  • “站点 URL”设置在哪里?
  • @Matt facebook UI 自从我发布后发生了很大变化,转到您的应用仪表板,选择左侧的“设置”,您将能够添加“域”和“站点 URL” "
【解决方案3】:

你好,我不确定这是否能帮助你尝试

    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'];
}]);

【讨论】:

    猜你喜欢
    • 2018-09-19
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 2015-04-02
    • 2020-10-24
    • 1970-01-01
    相关资源
    最近更新 更多