在用户注销后,如何防止浏览器的后退button访问受限制的信息?

我使用这个例子在github上find护照本地策略与mongoose/ mongodb。 我遇到的问题是当用户注销时,他们仍然可以通过点击浏览器上的后退button来访问受限制的信息。 我对node.js很陌生,但我想象一下,在执行后退和前进button之前,需要实现某种types的hook来调用ensureAuthenticated函数 – 位于代码的最底层。 在用户注销后,如何通过点击后退button来防止用户访问受限制的信息?

 var express = require('express') , passport = require('passport') , LocalStrategy = require('passport-local').Strategy , mongodb = require('mongodb') , mongoose = require('mongoose') , bcrypt = require('bcrypt') , SALT_WORK_FACTOR = 10; mongoose.connect('localhost', 'test'); var db = mongoose.connection; db.on('error', console.error.bind(console, 'connection error:')); db.once('open', function callback() { console.log('Connected to DB'); }); // User Schema var userSchema = mongoose.Schema({ username: { type: String, required: true, unique: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true}, accessToken: { type: String } // Used for Remember Me }); // Bcrypt middleware userSchema.pre('save', function(next) { var user = this; if(!user.isModified('password')) return next(); bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) { if(err) return next(err); bcrypt.hash(user.password, salt, function(err, hash) { if(err) return next(err); user.password = hash; next(); }); }); }); // Password verification userSchema.methods.comparePassword = function(candidatePassword, cb) { bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { if(err) return cb(err); cb(null, isMatch); }); }; // Remember Me implementation helper method userSchema.methods.generateRandomToken = function () { var user = this, chars = "_!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", token = new Date().getTime() + '_'; for ( var x = 0; x < 16; x++ ) { var i = Math.floor( Math.random() * 62 ); token += chars.charAt( i ); } return token; }; // Seed a user var User = mongoose.model('User', userSchema); // var usr = new User({ username: 'bob', email: 'bob@example.com', password: 'secret' }); // usr.save(function(err) { // if(err) { // console.log(err); // } else { // console.log('user: ' + usr.username + " saved."); // } // }); // Passport session setup. // To support persistent login sessions, Passport needs to be able to // serialize users into and deserialize users out of the session. Typically, // this will be as simple as storing the user ID when serializing, and finding // the user by ID when deserializing. // // Both serializer and deserializer edited for Remember Me functionality passport.serializeUser(function(user, done) { var createAccessToken = function () { var token = user.generateRandomToken(); User.findOne( { accessToken: token }, function (err, existingUser) { if (err) { return done( err ); } if (existingUser) { createAccessToken(); // Run the function again - the token has to be unique! } else { user.set('accessToken', token); user.save( function (err) { if (err) return done(err); return done(null, user.get('accessToken')); }) } }); }; if ( user._id ) { createAccessToken(); } }); passport.deserializeUser(function(token, done) { User.findOne( {accessToken: token } , function (err, user) { done(err, user); }); }); // Use the LocalStrategy within Passport. // Strategies in passport require a `verify` function, which accept // credentials (in this case, a username and password), and invoke a callback // with a user object. In the real world, this would query a database; // however, in this example we are using a baked-in set of users. passport.use(new LocalStrategy(function(username, password, done) { User.findOne({ username: username }, function(err, user) { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'Unknown user ' + username }); } user.comparePassword(password, function(err, isMatch) { if (err) return done(err); if(isMatch) { return done(null, user); } else { return done(null, false, { message: 'Invalid password' }); } }); }); })); var app = express(); // configure Express app.configure(function() { app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.engine('ejs', require('ejs-locals')); app.use(express.logger()); app.use(express.cookieParser()); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.session({ secret: 'keyboard cat' })); // CHANGE THIS SECRET! // Remember Me middleware app.use( function (req, res, next) { if ( req.method == 'POST' && req.url == '/login' ) { if ( req.body.rememberme ) { req.session.cookie.maxAge = 2592000000; // 30*24*60*60*1000 Rememeber 'me' for 30 days } else { req.session.cookie.expires = false; } } next(); }); // Initialize Passport! Also use passport.session() middleware, to support // persistent login sessions (recommended). app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); app.use(express.static(__dirname + '/../../public')); }); app.get('/users', function(req, res) { var users = User.find(); console.log(users); res.send(users); }); app.get('/', function(req, res){ res.render('index', { user: req.user }); }); app.get('/account', ensureAuthenticated, function(req, res){ res.render('account', { user: req.user }); }); app.get('/login', function(req, res){ res.render('login', { user: req.user, message: req.session.messages }); }); // POST /login // Use passport.authenticate() as route middleware to authenticate the // request. If authentication fails, the user will be redirected back to the // login page. Otherwise, the primary route function function will be called, // which, in this example, will redirect the user to the home page. // // curl -v -d "username=bob&password=secret" http://127.0.0.1:3000/login // /***** This version has a problem with flash messages app.post('/login', passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }), function(req, res) { res.redirect('/'); }); */ // POST /login // This is an alternative implementation that uses a custom callback to // acheive the same functionality. app.post('/login', function(req, res, next) { passport.authenticate('local', function(err, user, info) { if (err) { return next(err) } if (!user) { req.session.messages = [info.message]; return res.redirect('/login') } req.logIn(user, function(err) { if (err) { return next(err); } return res.redirect('/'); }); })(req, res, next); }); app.get('/logout', function(req, res){ req.logout(); res.redirect('/'); }); app.listen(3000, function() { console.log('Express server listening on port 3000'); }); // Simple route middleware to ensure user is authenticated. // Use this route middleware on any resource that needs to be protected. If // the request is authenticated (typically via a persistent login session), // the request will proceed. Otherwise, the user will be redirected to the // login page. function ensureAuthenticated(req, res, next) { if (req.isAuthenticated()) { return next(); } res.redirect('/login') } 

编辑
我想我可能会做些什么,但不能得到它的工作。 在做了更多的研究之后,看来我需要做的是防止本地caching。 我试图从我的app.configure函数中做到这一点:

 app.configure(function() { app.use(function(req, res, next) { res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'); next(); }); }); 

但是,这似乎并没有影响我的标题。

由于浏览器从caching中拉出该页面,那么在该页面上做什么并不重要,除非您添加JS检查以查看用户是否仍然通过身份validation…但这并不能解决页面存在的问题在caching中。

重新构造一个caching的问题,我发现这个答案: https : //stackoverflow.com/a/24591864/217374

自从你问了一年多了,所以我不希望你特别需要这个答案,但是对于那些来过的人来说,

当用户在浏览器中浏览时,数据显示在本地浏览器caching中,而不是从服务器请求。 你可以做什么,是添加一些JavaScript到你的注销事件。 那件js可以从浏览器历史logging中删除敏感页面。 您可以使用window.history来操作浏览器历史logging。 查看本指南来操作浏览器历史logging和window.history api 。

不知道这是否防弹。

将这些行添加到您的html(或查看文件)

 meta(http-equiv='Cache-Control', content='no-store, no-cache, must-revalidate') meta(http-equiv='Pragma', content='no-cache') meta(http-equiv='Expires', content='-1')