2013-04-12 23 views
5

Tôi đang sử dụng this example được tìm thấy trên github cho chiến lược hộ chiếu địa phương với mongoose/mongodb. Sự cố mà tôi gặp phải là khi người dùng đăng xuất, họ vẫn có thể truy cập thông tin bị hạn chế bằng cách nhấn nút quay lại trên trình duyệt. Tôi là loại mới với node.js nhưng tôi sẽ tưởng tượng rằng một số loại móc sẽ cần phải được thực hiện để gọi hàm ensureAuthenticated - nằm ở phía dưới cùng của mã - trước khi các nút quay lại và tiến lên được thực thi . Làm cách nào để ngăn người dùng truy cập vào thông tin bị hạn chế, bằng cách nhấn nút quay lại, sau khi người dùng đã đăng xuất?Làm cách nào để ngăn chặn nút quay lại của trình duyệt truy cập thông tin bị hạn chế sau khi người dùng đăng xuất?

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: '[email protected]', 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') 
} 

Sửa
Tôi nghĩ rằng tôi có thể là trên một cái gì đó nhưng không thể lấy nó để làm việc. Sau khi thực hiện một số nghiên cứu khác, Có vẻ như những gì tôi cần làm là ngăn chặn bộ đệm ẩn cục bộ. Tôi đang cố thực hiện điều này từ bên trong chức năng app.configure của mình:

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(); 
    }); 
}); 

Tuy nhiên, điều này dường như không ảnh hưởng đến tiêu đề của tôi.

Trả lời

0

Khi người dùng điều hướng trở lại trong trình duyệt, dữ liệu được hiển thị từ bộ nhớ cache của trình duyệt cục bộ và không được yêu cầu từ máy chủ của bạn. Những gì bạn có thể làm, là thêm một số javascript vào sự kiện đăng xuất của bạn. Phần js đó có thể xóa các trang nhạy cảm khỏi lịch sử trình duyệt. Bạn có thể làm việc với window.history để thao tác lịch sử trình duyệt. Hãy xem trong this guide for manipulating the browser historywindow.history api.

Không chắc chắn nếu điều này là chống đạn.

2

Vì trình duyệt kéo trang đó khỏi bộ nhớ cache, việc bạn bạn làm gì trên trang đó, trừ khi bạn thêm kiểm tra JS để xem liệu người dùng vẫn được xác thực ... nhưng điều đó không giải quyết được vấn đề của trang đang ở trong bộ nhớ cache.

Tái định hình các vấn đề như một bộ nhớ cache một, tôi thấy câu trả lời này: https://stackoverflow.com/a/24591864/217374

Đã hơn một năm kể từ khi bạn yêu cầu, vì vậy tôi không mong đợi bạn đặc biệt cần câu trả lời nữa, nhưng có nó là cho bất kỳ ai khác đến.

0

Thêm các dòng này vào html của bạn (hoặc xem tệp)

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') 
Các vấn đề liên quan