Node.js多文件引入passport为何能识别Google Strategy配置
核心原因:Node.js 模块缓存机制
你误以为两个文件中引入的是不同的passport实例,实际上两次require("passport")拿到的是完全相同的单例对象,这是Node.js CommonJS 模块规范的默认加载规则决定的:
- Node.js 首次加载某个模块(包括npm安装的第三方包)时,会执行模块全部代码,将最终导出的结果存入内存缓存
- 后续在项目任意文件中再次
require同一个模块时,Node.js不会重新执行模块代码,直接返回内存中缓存的导出结果 - passport包本身导出的就是预先实例化好的全局认证对象,而非可实例化的类,不存在每次引入都新建实例的逻辑
对应你的代码执行流程
- 入口文件
index.js最先执行require("./services/passport"):- 首先加载passport包,将导出的passport单例存入缓存
- 执行你写的配置逻辑,调用
passport.use()把初始化好的Google Strategy(包含clientID、clientSecret、callbackURL等全部配置)注册到passport内部的策略映射表中,该策略默认的名称就是google
- 后续加载
authRoutes.js时,文件内的const passport = require("passport")直接从缓存中拿到已经完成Google策略注册的同一个passport对象 - 当路由中调用
passport.authenticate("google")时,passport会从内部维护的策略映射表中,找到之前注册好的名为google的策略实例,自然可以读取到所有配置参数完成认证逻辑
验证方式
你可以自行做个小测试验证单例特性:
在services/passport.js中给passport对象加一个自定义属性:
// services/passport.js const passport = require("passport"); passport._customFlag = "配置文件设置的自定义标记"; // 剩下的原有Google策略配置代码不变
在authRoutes.js中打印这个属性:
// authRoutes.js const passport = require("passport"); console.log(passport._customFlag); // 运行后会正常输出「配置文件设置的自定义标记」,证明两个文件拿到的是同一个对象
相关代码参考
Index.js
const express = require("express"); require("./services/passport"); const app = express(); require("./routes/authRoutes")(app); app.listen(5000);
services文件夹下的passport.js
const passport = require("passport"); const GoogleStrategy = require("passport-google-oauth20").Strategy; const keys = require("../config/keys"); passport.use( new GoogleStrategy( { clientID: keys.googleClientID, clientSecret: keys.googleClientSecret, callbackURL: "/auth/google/callback", }, (accessToken, refreshToken, profile, done) => { console.log("accessToken", accessToken); console.log("refreshToken", refreshToken); console.log("profile", profile); console.log("done", done); } ) );
authRoute.js
const passport = require("passport"); // 此处引入的passport和配置文件中是同一个实例,因此可以读取到已注册的Google策略配置 module.exports = (app) => { app.get( "/auth/google", passport.authenticate("google", { scope: ["profile", "email"], }) ); app.get("/auth/google/callback", passport.authenticate("google")); };
内容的提问来源于stack exchange,提问作者Laxus
相关产品推荐
相关产品推荐

