【问题标题】:How to set the current host for Passport strategy callbackURL?如何为 Passport 策略 callbackURL 设置当前主机?
【发布时间】:2025-12-09 01:35:01
【问题描述】:

我在 Passport with Express 中使用 Passport-Linkedin 策略,以允许用户使用他们的 LinkedIn 个人资料登录。

我有以下代码:

passport.use(new LinkedInStrategy({
    consumerKey: config.linkedin.LINKEDIN_API_KEY,
    consumerSecret: config.linkedin.LINKEDIN_SECRET_KEY,
    callbackURL: "http://localhost:3000/auth/linkedin/callback"
  },
  function(token, tokenSecret, profile, done) {
    // asynchronous verification, for effect...
    process.nextTick(function () {

      // To keep the example simple, the user's LinkedIn profile is returned to
      // represent the logged-in user.  In a typical application, you would want
      // to associate the LinkedIn account with a user record in your database,
      // and return that user instead.
      return done(null, profile);
    });
  }
));

在第 4 行,我必须手动设置完整的回调 URL。我有一个用于生产的字符串,一个用于开发的字符串,但是我的 URL 不断变化,端口也是如此(我使用 2 台机器进行开发)。

如何自动设置 URL 的第一部分 (http://localhost:3000)? expressapp 的属性是否允许我这样做?我需要求助于app.use(function(req, res){});吗?

谢谢!

【问题讨论】:

    标签: javascript node.js express passport.js


    【解决方案1】:

    老问题,可能只对较新版本有效。但是,如果有人像我一样遇到这种情况,解决方案就是不在callbackURL 中指定主机名:

    passport.use(new LinkedInStrategy({
        consumerKey: config.linkedin.LINKEDIN_API_KEY,
        consumerSecret: config.linkedin.LINKEDIN_SECRET_KEY,
        callbackURL: "/auth/linkedin/callback"
      },
    

    为了让这适用于 heroku https 重定向,我们必须通过信任代理来告诉系统信任 x-forwarded-protocol 标头:

    passport.use(new LinkedInStrategy({
        consumerKey: config.linkedin.LINKEDIN_API_KEY,
        consumerSecret: config.linkedin.LINKEDIN_SECRET_KEY,
        callbackURL: "/auth/linkedin/callback",
        proxy: true
      },
    

    【讨论】:

    • 如果您的应用不在根路径上运行,则它不起作用,例如它在/myapp 而不是/ 上运行。
    【解决方案2】:

    最终通过从 URL 和实际端口动态构建回调 URL 解决了这个问题。对此解决方案不满意,因为它看起来不优雅,但如果不添加中间件使用调用(我确信这比简单的字符串连接更能影响性能),就无法找到获取实际 URL 的方法。

    【讨论】:

      【解决方案3】:

      在我的 config.js 中有一个 cfg.site_url,这是一种方式,或者你可以查看 req.host

      http://expressjs.com/api.html#req.host

      // Host: "example.com:3000"
      req.hostname
      // => "example.com"
      

      不确定你的上下文中是否有 req 对象。

      【讨论】:

      • 我从配置字符串开始,但服务器名称和端口不断变化。我在应用程序级别 - 据我所知,获得 req 的唯一方法是添加我提到的 app.use 语句。问题是,它会被每个请求调用。
      • 你可以为你的一个请求提供一个中间件。 loadConfigVariable 函数中的 app.get('/whatever', loadConfigVariable, routes.whatever);app.locals.whatever = config.whatever 之类的东西。
      • 这就是我试图避免的——另一条路线。我想知道我是否可以在 Passport 本身中找到该功能?
      • 我不是护照人,所以也许有办法。