将 AngularJS 与 PassportJS 结合时出现 CORS 问题

Posted

技术标签:

【中文标题】将 AngularJS 与 PassportJS 结合时出现 CORS 问题【英文标题】:CORS issue when combining AngularJS with PassportJS 【发布时间】:2015-12-03 02:49:48 【问题描述】:

我正在尝试将 ExpressJS + PassportJS 与 Angular SPA 应用程序结合起来。问题可能出在 CORS 标头中。

这是我想要完成的:

客户端视图

<a class="btn btn-block btn-social btn-twitter" ng-click="twitter()">
    <i class="fa fa-twitter"></i> Sign in with Twitter
</a>

客户端控制器

以下方法正确吗?

$scope.twitter = function() 
  $http.get('oauth/twitter').then(function(res) 
    // Fetch the user from response and store it somewhere on the client side
  );
;

负责处理身份验证的服务器端如下所示:

服务器路由

app.get('/oauth/twitter', passport.authenticate('twitter', 
  failureRedirect: '/signin'
));

app.get('/oauth/twitter/callback', passport.authenticate('twitter', 
  failureRedirect: '/signin',
  successRedirect: '/'
));

推特策略

passport.use(new TwitterStrategy(
  consumerKey: config.twitter.clientID,
  consumerSecret: config.twitter.clientSecret,
  callbackURL: config.twitter.callbackURL,
  passReqToCallback: true
, function (req, token, tokenSecret, profile, done) 
  var providerData = profile._json;
  providerData.token = token;
  providerData.tokenSecret = tokenSecret;

  var providerUserProfile = 
    fullName: profile.displayName,
    username: profile.username,
    provider: 'twitter',
    providerId: profile.id,
    providerData: providerData
  ;

  users.saveOAuthUserProfile(req, providerUserProfile, done);
));

用户服务器控制器

exports.saveOAuthUserProfile = function (req, profile, done) 
  User.findOne(
    provider: profile.provider,
    providerId: profile.providerId
  , function (err, user) 
    if (err) 
      return done(err);
     else 
      if (!user) 
        var possibleUsername = profile.username || ((profile.email) ? profile.email.split('@')[0] : '');

        User.findUniqueUsername(possibleUsername, null, function (availableUsername) 
          profile.username = availableUsername;
          user = new User(profile);
          user.fullName = profile.fullName;

          user.save(function (err) 
            if (err) 
              var message = getErrorMessage(err);
              req.flash('error', message);
              return done(err);
            

            return done(err, user);
          );
        );
       else 
        return done(err, user);
      
    
  );
;

当我在浏览器 (Chrome/Firefox) 中单击 Sign in with Twitter 时,我看到正在发出以下请求:

    GET http://localhost:3000/oauth/twitter(302 暂时移动) GET https://api.twitter.com/oauth/authenticate?oauth_token=Zz014AAAAAAAg5HgAA******** (307 内部重定向)

浏览器抱怨缺少“Access-Control-Allow-Origin”标头。

为了解决这个问题,我尝试使用像这样的cors

var cors = require('cors');
api.use(cors());

并且还手动设置所有响应的标题,没有效果。

你能给我指路吗? 问候

【问题讨论】:

【参考方案1】:

我遇到了类似的问题,无法在代码中修复它。于是我找到了这个 Chrome 扩展:Allow-Control-Allow-Origin: *

您可以设置 URL 模式并启用跨域资源共享。

完成工作后别忘了禁用它!

【讨论】:

【参考方案2】:

尝试在nodejs中设置header,而不是使用cors模块

app.use(function(req, res, next) 
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
);

【讨论】:

无效。 AFAIR 这个中间件不能影响来自不同主机的响应(在这种情况下是api.twitter.com

以上是关于将 AngularJS 与 PassportJS 结合时出现 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

我正在尝试将 PassportJs 与多种类型的用户一起使用(每个用户都有不同的模型)。我究竟做错了啥?

如何使passportjs google login oauth与JWT一起使用,而不是通过序列化/反序列化方法创建会话?

防止访问 AngularJS 中的管理页面

Nuxt auth 与passportjs?

Express 会话与 PassportJS 会话

谁能帮我解决与passportjs相关的错误