使用express的Passsport认证会在不同的机器上显示之前登录的用户的信息。如何防止这种情况的发生?

问题描述 投票:0回答:1

我有一个react应用程序,使用express服务器的护照认证策略。在我的本地机器上,我的设置是在一个端口启动服务器(app.js),在另一个端口启动react应用。而且我能够使用护照成功认证。在托管环境中,服务器会负责启动服务器,并将react客户端建立到公共文件夹中。

我的问题是,当我把我的代码推送到托管环境后,托管环境启动了Express服务器(node app.js),并将react应用构建到公共文件夹。即使我能够使用护照进行身份验证,并且能够接收用户信息,但如果其他人从不同机器的不同浏览器登录,那么该用户的资料在我的浏览器中是可用的。

app.js

const express = require('express');
const passport = require('passport');        
...
let user = {}; //this is an object to store the profile data
...
passport.serializeUser(function (user, done) {
    done(null, user);
});

passport.deserializeUser(function (obj, done) {
    done(null, obj);
});
var OpenIDConnectStrategy = require('passport-ci-oidc').IDaaSOIDCStrategy;
var Strategy = new OpenIDConnectStrategy({
    clientID: settings.client_id,
    clientSecret: settings.client_secret,
    callbackURL: settings.callback_url,
    function (iss, sub, profile, accessToken, refreshToken, params, done) {
        process.nextTick(function () {
            user = {...profile}
            profile.accessToken = accessToken;
            profile.refreshToken = refreshToken;
            done(null, profile);
        })
    }
);

passport.use(Strategy);
app.use(express.static(__dirname + '/public'));

app.get('/login', passport.authenticate('openidconnect', {}));

app.get('/oidc_callback', function (req, res, next) {
    passport.authenticate('openidconnect', {
        successRedirect: redirect_url,
        failureRedirect: '/failure',
    })(req, res, next);
});

app.get('/user', function (req, res) {  //This is the api i use to access user information in ract page
  res.send(user);
});

app.get('/logout', function (req, res) {
    user = {};                         //empty the user data object
    req.session.destroy();
    req.logout();
    res.end();
});

这里我们可以看到我使用了一个 user 对象来存储用户数据,并创建了一个 API /user (app.get('/user' ...) 来访问我的客户端react应用程序的用户数据。

访问用户数据的React组件

constructor() {
    super()
    this.state = {
      loggedUser: []
    }
  }

  componentDidMount() {
    axios.get('/user')       //If I'm testing with local the API will be https://localhost:5000 - node server
      .then(res => {
        const loggedUser = res.data; 
        this.setState({ loggedUser });
      }).catch(err => {
      console.log("Fetch error", err)
    })
  }
node.js reactjs express passport.js
1个回答
0
投票

编辑。 用新的数据编辑了问题后,完全复习了答案。

首先,我们需要一个唯一的键在 profile 来唯一标识一个用户,在我的例子中,我使用了 "oid" 但你可以使用更适合你的要求。

你可以尝试修改以下代码。

let user = {}; //this is an object to store the profile data

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

passport.deserializeUser(function (obj, done) {
    done(null, obj);
});

// Later ...
function(iss, sub, profile, accessToken, refreshToken, params, done) {
    process.nextTick(function () {
        user = {...profile}
        profile.accessToken = accessToken;
        profile.refreshToken = refreshToken;
        done(null, profile);
    })
}

with:

let uniqueKey = "oid"; // The field name of profile which uniquely identify a user
let users = {};

passport.serializeUser((user, done) => done(null, (users[user[uniqueKey]] = user)[uniqueKey]));
passport.deserializeUser((key, done) => done(null, users[key]));

// Later ...
(iss, sub, profile, accessToken, refreshToken, params, done) => done(null, { ...profile, accessToken, refreshToken })
// or
(iss, sub, profile, accessToken, refreshToken, params, done) => {
    process.nextTick(() => done(null, { ...profile, accessToken, refreshToken }));
}

这些都是async函数,所以当我说的时候 返回 我的意思是通过 done 回调函数。

首次登录功能 只需退还 user 对象 passport-ci-oidc 似乎需要在 process.nextTick,你可以尝试用或不用它)。)

serializeUser 确实需要 序列化 用户对象,在我们的例子中,这意味着只是将其存储在内存中。users[user[uniqueKey]] = user 然后返回唯一的密钥,以后护照应该用它来反序列化同一个用户。done(null, user[uniqueKey]).

如上次 deserializeUser 需要通过给定的识别密钥来返回用户对象,在我们的例子中,只是为了从内存中返回它。done(null, users[key]).

希望能帮到你

© www.soinside.com 2019 - 2024. All rights reserved.