快速登录会话仅持续一页视图

Posted

技术标签:

【中文标题】快速登录会话仅持续一页视图【英文标题】:Express login session only lasts one page view 【发布时间】:2021-12-10 07:48:40 【问题描述】:

在下面的代码中,当我第一次访问/(未登录FB)时,我被重定向到/login页面,正如预期的那样。

然后我登录 facebook,然后按预期转到/

如果我随后刷新页面(在/ 上),我将收回/login 页面,就好像会话已经结束一样。

对于/ 的每次新页面浏览,我总是被要求每次登录。

我做错了什么?

(出于测试目的,我还没有使用真正的数据库,只是为了会话而设置了这个初步的 user.js ..)

user.js

import fs from 'fs'

if (!fs.existsSync('./user.json')) 
  fs.writeFileSync('./user.json', JSON.stringify(null))


export default 

  query(facebookId) 
    let user = JSON.parse(fs.readFileSync('./user.json', 'utf8'));

    if (user && user.facebookId === facebookId) 
      return user
    

    return null
  ,

  save(user) 
    fs.writeFileSync('./user.json', JSON.stringify(user, null, 2))
    return user
  ,

  delete() 
    fs.writeFileSync('./user.json', JSON.stringify(null, null, 2))
    return true
  

server.js

import  Strategy as FacebookStrategy  from 'passport-facebook'
import express                          from 'express'
import passport                         from 'passport'
import session                          from 'express-session'
import fetch                            from 'node-fetch'
import  fileURLToPath                 from 'url'
import  dirname                       from 'path'
import cors                             from 'cors'
import cookieParser                     from 'cookie-parser'
import  ensureLoggedIn                from 'connect-ensure-login'
import FB                               from './fb'
import USER                             from './user'
import bodyParser                       from 'body-parser'

const jsonParser = bodyParser.json()
    
const 
  PORT,
  INSTAGRAM_USER_ID,
  FACEBOOK_APP_ID,
  FACEBOOK_APP_SECRET,
  FACEBOOK_PAGE_NAME
 = process.env

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

const app = express()

app.use(cors(
   origin: '*',
   credentials: true,
   optionSuccessStatus: 200
))

app.use(function(req, res, next) 
  res.header('Access-Control-Allow-Origin', `http://localhost:$PORT`)
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization')
  res.header('Access-Control-Allow-Methods', 'POST, GET')
  next()
)

app.use(cookieParser())
app.use(bodyParser.json(limit: "50mb"));
app.use(bodyParser.urlencoded(limit: "50mb", extended: true, parameterLimit:50000))
app.use(session( secret: 'googoogaga', resave: false, saveUninitialized: false ))
app.use(passport.initialize())
app.use(passport.session())

passport.use(new facebookStrategy(
  clientID        : FACEBOOK_APP_ID,
  clientSecret    : FACEBOOK_APP_SECRET,
  callbackURL     : `http://localhost:$PORT/facebook/callback`,
  profileFields: ['id', 'displayName']

, function(accessToken, refreshToken, profile, done) 

    let user = USER.query(profile.id)

    if (user) 
      return done(null, user)
     else 
      user = USER.save(
        facebookId: profile.id,
        accessToken
      )
      return done(null, user);
    

));

passport.serializeUser(function(user, done) 
    done(null, user);
);

passport.deserializeUser(function(user, done) 
    done(null, user);
);
    
app.get('/auth/facebook', passport.authenticate('facebook',  scope:'email,instagram_basic,pages_show_list' ));

app.get('/facebook/callback', passport.authenticate('facebook', 
  successRedirect : '/',
  failureRedirect : '/login'
));

app.get('/login', (req,res) => 
  res.sendFile(__dirname + '/public/login.html');
)

app.get('/', ensureLoggedIn('/login'), (req,res) => 
  res.status(200).send( user: req.user )
)

app.get('/logout', function(req, res)
  req.session.destroy(()=>
    USER.delete()
    res.redirect('/login')
  )
)  

app.listen(PORT)

【问题讨论】:

【参考方案1】:

因为nodemon

每次用户登录时,我都会更新一些文件,但我忘记告诉 nodemon 忽略这些更改,因此服务器每次都会因这些文件更改而重新启动。

每当服务器重新启动时,会话也会被重置。

小心 nodemon,确保将服务器将要更改的所有文件放在文件夹中,并告诉 nodemon 忽略它。

另一方面,服务器也可能因其他原因重新启动。为什么每次都要重置会话?没有办法解决吗?。

【讨论】:

您正在为会话使用内存存储(这是默认选项)。如果进程重新启动,它会丢失内存。您可以使用 mysql 存储或 Redis 存储来进行持久会话存储。看看expressjs.com/en/resources/middleware/…

以上是关于快速登录会话仅持续一页视图的主要内容,如果未能解决你的问题,请参考以下文章

视图之间的 Django 身份验证

如何在我的应用程序中使用 Facebook 登录并在成功登录后移至下一页/视图控制器?

Django 自定义登录视图 -> 会话不持久

javax.faces.application.ViewExpiredException:无法恢复视图

如何快速保持会话

iPhone Page Control 仅显示在 UIScrollView 的第一页上