Javascript 如何在启动时将持久会话初始化到passport/会话文件存储中?

Javascript 如何在启动时将持久会话初始化到passport/会话文件存储中?,javascript,node.js,session,passport.js,Javascript,Node.js,Session,Passport.js,此express应用程序使用passport向azure进行身份验证。当用户进行身份验证时,用户数据将保存到内存存储中,然后将其写入会话存储中 当express应用程序重新启动时,它将从会话存储中加载以前保存的用户数据。但是,passport不能识别以前经过身份验证的用户,需要他们重新进行身份验证。这是一个问题,因为该应用程序仍在开发中,需要频繁重新启动 我希望应用程序在重新启动后识别以前经过身份验证的用户。 更新:经过进一步研究,我发现会话由express session包管理。我已将会话文

此express应用程序使用passport向azure进行身份验证。当用户进行身份验证时,用户数据将保存到内存存储中,然后将其写入会话存储中

当express应用程序重新启动时,它将从会话存储中加载以前保存的用户数据。但是,passport不能识别以前经过身份验证的用户,需要他们重新进行身份验证。这是一个问题,因为该应用程序仍在开发中,需要频繁重新启动

我希望应用程序在重新启动后识别以前经过身份验证的用户。


更新:经过进一步研究,我发现会话由
express session
包管理。我已将
会话文件存储
包添加到代码中,并将其配置为保存会话。这些会话仍然不会持续


这个应用程序就是从这个开始的。它将用户数据序列化并反序列化到内存存储中,我添加了代码来持久化数据。但存储的用户数据与浏览器中存储的会话密钥之间存在断开连接

应用程序使用用户的
oid
作为键来存储用户,如下所示:

{
    "1aa31bba-xxxx-xxxx-xxxx-xxxx": {
        "profile": {
            "sub": "_v3k8L5PkIREMis1in9IF3SucjEQqxRxThsoK35rBZQ",
            "oid": "1aa31bba-xxxx-xxxx-xxxx-xxxx",
            ...
        }
    }
}
但是,浏览器的会话cookie不是oid:

"connect.sid":"s:cd957624-72ba-4552-893d-8fd59bbce31e.Gt87eHx0WjkKXOKeq6oDvsw35BZZ+6ZQ6p0c3dwjRTE"
cookie
connect.sid
是浏览器中存储的唯一cookie。每次用户重新验证时,cookie的值都会更改。此cookie不会写入用户文件或会话文件。这就是我不知道如何解决的脱节

在启动之前的会话时,初始化会话文件存储的正确方法是什么?

这是申请者的护照代码

var passport = require('passport');
var OIDCStrategy = require('passport-azure-ad').OIDCStrategy;
var FileStore = require('session-file-store')(session);  // added to test FileStore

require('dotenv').config();

var users = {};
var userStore = require('userStore');
users = userStore.load();

// Passport calls serializeUser and deserializeUser to manage users
passport.serializeUser(function (user, done) {
    // Use the OID property of the user as a key
    users[user.profile.oid] = user;
    userStore.save(users);
    done(null, user.profile.oid);
});

passport.deserializeUser(function (id, done) {
    done(null, users[id]);
});

const oauth2 = require('simple-oauth2').create({
    client: {
        id: process.env.OAUTH_APP_ID,
        secret: process.env.OAUTH_APP_PASSWORD
    },
    auth: {
        tokenHost: process.env.OAUTH_AUTHORITY,
        authorizePath: process.env.OAUTH_AUTHORIZE_ENDPOINT,
        tokenPath: process.env.OAUTH_TOKEN_ENDPOINT,
    }
});

async function signInComplete(iss, sub, profile, accessToken, refreshToken, params, done) {
    if (!profile.oid) {
        return done(new Error("No OID found in user profile."));
    }
    try {
        const user = await graph.getUserDetails(accessToken);
        if (user) {
            // Add properties to profile
            profile['email'] = user.mail ? user.mail : user.userPrincipalName;
        }
    } catch (err) {
        return done(err);
    }
    // Create a simple-oauth2 token from raw tokens
    let oauthToken = oauth2.accessToken.create(params);
    // Save the profile and tokens in user storage
    users[profile.oid] = { profile, oauthToken };
    return done(null, users[profile.oid]);
}

passport.use(new OIDCStrategy(
    {
        identityMetadata: `${process.env.OAUTH_AUTHORITY}${process.env.OAUTH_ID_METADATA}`,
        clientID: process.env.OAUTH_APP_ID,
        responseType: 'code id_token',
        responseMode: 'form_post',
        redirectUrl: process.env.OAUTH_REDIRECT_URI,
        allowHttpForRedirectUrl: true,
        clientSecret: process.env.OAUTH_APP_PASSWORD,
        validateIssuer: false,
        passReqToCallback: false,
        scope: process.env.OAUTH_SCOPES.split(' ')
    },
    signInComplete
));

app.use(session({
    secret: process.env.SESSION_SECRET_KEY,
    store: new FileStore({}), // added to test FileStore
    genid: uuid,
    resave: true, // false,  // changed to test FileStore
    saveUninitialized: true, // false,  // changed to test FileStore
    unset: 'destroy'
}));

app.use(passport.initialize());
app.use(passport.session());

下面的更改应该会有所帮助,因为我不确定“sessionStore”是在内存中创建的,一旦重新启动应用程序,用户列表将删除并再次注册

var passport=require('passport');
var OIDCSTRAGEY=require('passport-azure-ad')。OIDCSTRAGEY;
require('dotenv').config();
//理想情况下,这需要用DB替换
var用户=[];
//如果存在DB,则不需要这样做
让getUser=(id)=>{
for(让index=0;index{
for(让index=0;index{
if(profile.oid){
if(checkIfUserExists(profile.oid)){
//getUser和return user,如果DB此部分将更改
let user=getUser(profile.oid);
让userDetails={};
试一试{
userDetails=wait graph.getUserDetails(accessToken);
}捕获(错误){
返回完成(错误);
}
user.userDetails=userDetails;
user.oauthToken=oauth2.accessToken.create(参数);
返回完成(空,用户);
}否则{
//创建一个新用户并返回用户,将在db就位时更改
让userDetails={};
试一试{
userDetails=wait graph.getUserDetails(accessToken);
}捕获(错误){
返回完成(错误);
}
//根据当前代码,用户结构保留了我的最佳状态
让newUser={
id:profile.oid,
userDetails:userDetails,
简介:简介,,
oauthToken:oauth2.accessToken.create(参数)
};
push(newUser);
返回完成(null,newUser)
}
}否则{
返回完成(新错误(“在用户配置文件中找不到OID”);
}
});
}
passport.使用(新策略)(
{
identityMetadata:“${process.env.OAUTH_AUTHORITY}${process.env.OAUTH_ID_METADATA}”,
clientID:process.env.OAUTH_APP_ID,
responseType:'代码id_令牌',
responseMode:“表单发布”,
重定向URL:process.env.OAUTH_REDIRECT_URI,
allowHttpForRedirectUrl:true,
clientSecret:process.env.OAUTH_APP_密码,
验证者:错,
passReqToCallback:false,
作用域:process.env.OAUTH_SCOPES.split(“”)
},
完成
));
//有关此部分,请参阅护照文档
应用程序使用(会话)({
机密:process.env.SESSION\u secret\u密钥,
精灵:uuid,
resave:false,//一旦有了存储,就更改为true
saveUninitialized:false//一旦有了存储,就更改为true
}));
app.use(passport.initialize());
app.use(passport.session());

作为参考,

根本原因是
user.oauthtoken
对象是类
AuthToken
的实例。当用户被序列化到存储器时,json只记录obj
passport.deserializeUser(function (id, done) {
    done(null, users[id]);
});
passport.deserializeUser(function (id, done) {
    let user = users[id];
    if( user.oauthToken.constructor.name !== "AccessToken" ) {
        user.oauthToken = oauth2.accessToken.create(user.oauthToken.token);
    }
    done(null, user);
});