MEAN 堆栈 Facebook 授权错误:没有“Access-Control-Allow-Origin”标头?

Mic*_*ael 5 javascript facebook node.js express angularjs

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

\n\n
XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%\xe2\x80\xa62Flocalhost%3A3030%2Fauth%2Ffacebook%2Fcallback&client_id=....  \nNo \'Access-Control-Allow-Origin\' header is present on the requested resource. Origin \'http://localhost:3030\' is therefore not allowed access.\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

我做错了什么以及如何解决?

\n\n

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

\n\n
app.get(\'/auth/facebook\', passport.authenticate(\'facebook\'));\n\napp.get(\'/auth/facebook/callback\', passport.authenticate(\'facebook\', {\n    successRedirect: \'/success\',\n    failureRedirect: \'/error\'\n}));\n\napp.post(\'/success\', function(req, res, next) {\n    User.findById(req.session.passport.user, function(err, user) {\n        if(err){ \n            res.send({success:false}); \n        }else{ \n            res.send({success:true,user: user});\n        }\n    });\n});\n\napp.get(\'/logout\', function(req, res){\n    req.logout();\n    res.redirect(\'/\');\n    res.end();\n});\n\napp.post(\'/error\', function(req, res, next) {\n    res.send({success:false});\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的passport.js文件(服务器端):
\n注意: clientIDclientSectret、 和callbackURL位于另一个文件 ( config.js) 中。但它们是有效的。

\n\n
passport.use(new FacebookStrategy({\n    clientID: config.facebookAuth.clientID,\n    clientSecret: config.facebookAuth.clientSecret,\n    callbackURL: config.facebookAuth.callbackURL\n    },\n    function(accessToken, refreshToken, profile, done) {\n        User.findOne({ oauthID: profile.id }, function(err, user) {\n            if(err) { console.log(err); }\n            if (!err && user != null) {\n                done(null, user);\n            } else {\n                var user = new User({\n                    oauthID: profile.id,\n                    name: profile.displayName,\n                    created: Date.now()\n                });\n                user.save(function(err) {\n\n                    if(err) {\n                        console.log(err);\n                    } else {\n                        console.log("saving user ...");\n                        done(null, user);\n                    }\n                });\n            }\n        });\n    }\n));\n\n\n// serialize and deserialize\npassport.serializeUser(function(user, done) {\n    console.log(\'serializeUser: \' + user._id)\n    done(null, user._id);\n});\npassport.deserializeUser(function(id, done) {\n    User.findById(id, function(err, user){\n        console.log(user)\n        if(!err) {done(null, user);}\n        else {done(err, null)}\n    });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
var express = require(\'express\'),\n    passport = require(\'passport\'),\n    cookieParser = require(\'cookie-parser\'),\n    bodyParser = require(\'body-parser\'),\n    session = require(\'express-session\'),\n    cors = require(\'cors\');\n\nvar whitelist = [\'https://www.facebook.com\'];\nvar corsOptions = {\n  origin: function(origin, callback){\n    var originIsWhitelisted = whitelist.indexOf(origin) !== -1;\n    callback(null, originIsWhitelisted);\n  }\n};\n\nmodule.exports = function (app, config) {\n    app.set(\'view engine\', \'ejs\');\n    app.use(cookieParser());\n    app.use(bodyParser());\n    app.use(cors(corsOptions));\n    app.use(session({secret:"car advisor secret"}));\n    app.use(passport.initialize());\n    app.use(passport.session());\n    app.use(express.static(config.rootPath+"/public"));\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

客户端

\n\n

这是我的 html 文件:

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

这是我的登录控制器:

\n\n
$scope.signin = function(username, password) {\n    authService.authenticateUser(username, password).then(function(success) {\n        if (success){\n            console.log("You have successfully signed in!");\n        }\n    });\n}\n\n$scope.signout = function() {\n    authService.logoutUser().then(function() {\n        console.log("You have successfully signed out!");\n        $location.path(\'/\');\n    });\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

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

Hen*_*ves 0

您不能向不同的地址发出 ajax 请求。即使地址相同且端口不同,您也会遇到“同源策略”问题。

您可以使用 nginx 并使用 重定向请求来完成此操作proxy_pass

检查: http://distinctplace.com/infrastruct/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/(...);
  }
}
Run Code Online (Sandbox Code Playgroud)