问题描述
我已经创建了一个基本的登录页面,成功登录后,用户将被重定向到成功页面。 在成功页面中,它们是一个标签,该标签通过get request重定向到/ logout并破坏会话并重定向到homepage。我的问题是,如果用户打开了该应用程序的2个实例并从一个选项卡注销,则另一个instanace(tab)正常工作,直到刷新页面,然后显示“禁止”。所以我该怎么做才能从两个选项卡中注销,就像facebook或amazon一样,这里是代码:
const express = require('express');
const url= require('url');
const db=require('./dao.js');
var bodyParser = require('body-parser')
const session = require("express-session");
const app= express();
const nunjucks=require("nunjucks");
const path = require('path');
const Pin=require('./models/pin');
const User=require('./models/users');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.resolve(__dirname,'public')));
nunjucks.configure(path.resolve(__dirname,'views'),{
express:app,autoscape:true,noCache:false,watch:true
});
app.use(session({
secret: "session",resave: false,saveUninitialized: true,cookie: { secure: false }
}));
//passoprt consfig
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function (user,done) {
done(null,user.id);
});
passport.deserializeUser(function (user,next) {
next(null,user);
});
passport.use('local',new LocalStrategy((username,password,done) => {
User.findOne({ username: username },(err,user) => {
if (err) { return done(err); }
if (!user) { return done(null,null,{ message: 'No user found!' }); }
if (user.password !== password) {
return done(null,{ message: 'Username or password is incorrect!' });
}
return done(null,user,null);
});
}
));
function isAuthenticated(req,res,next) {
if (req.isAuthenticated()) {
next();
} else {
req.session.destroy();
res.status(403).send('Forbidden');
}
}
app.get("/",(req,res)=>{
console.log("hi");
res.render("validate.html",{});
});
app.post('/login',res) => {
// passport.authenticate('local',{ successRedirect: '/admin',failureRedirect: '/login' }
passport.authenticate('local',function (err,info) {
// console.log(err,info);
if (err) {
res.render('validate.html',{ error: err });
} else if (!user) {
res.render('validate.html',{ errorMessage: info.message });
} else {
//setting users in session
req.logIn(user,function (err) {
if (err) {
res.render('/',{ error: err });
} else {
res.redirect('/success');
}
})
}
})(req,res);
});
app.get('/success',isAuthenticated,res)=>{
res.render("index.html",{});
})
app.get("/logout",function (req,res) {
req.session.destroy();
res.redirect('/');
});
app.get("/pincode",res)=>{
console.log(req.query.pincode);
let pin=req.query.pincode;
let pattern= /^[0-9]*$/;
if(pattern.test(pin)){
Pin.find({pincode:pin},data)=>{
if(err)
{
console.log("error");
}
else
{
console.log(data);
//res.render('index.html',{data:data});
res.status(200).send(data);
//res.status(200).json(data);
}
});
}
else{
res.status(200).send("Nan");
//res.render('index.html',{nomessage:"Not a no"});
}
// res.redirect('http://google.com');
});
app.listen(80,()=>{
console.log("App running at port 80");
});
<!doctype html>
<html lang="en">
<head>
<!-- required Meta tags -->
<Meta charset="utf-8">
<Meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkmxe40PTknxrLnZ9+fkDaog==" crossorigin="anonymous" />
<link rel="stylesheet" href="css/style.css">
<title>Hello,world!</title>
</head>
<body>
<div class="div1">
<div class="container-sm">
<div class="row">
<form action="/login" method="POST" class="col-12" id=form autocomplete="off">
<p class="text-danger">{{message}}</p>
<p class="text-danger">{{error}}</p>
<p class="text-danger">{{errorMessage}}</p>
<input type="text" name="username" id="pin" placeholder="enter email" >
<input type="password" name="password" placeholder="enter passowrd">
<button type="submit" id=btn>login</button>
</form>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first,then Popper.js,then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
<!-- begin snippet: js hide: false console: true babel: false -->
解决方法
此博客可能会有所帮助,
https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/
基于博客
如果我登录不同的选项卡会怎样?
解决此问题的一种方法是通过在localstorage上引入全局事件侦听器。每当我们在一个选项卡上的localstorage中更新此注销键时,侦听器都会在其他选项卡上触发并触发“注销”,并将用户重定向到登录屏幕。
window.addEventListener('storage',this.syncLogout)
//....
syncLogout (event) {
if (event.key === 'logout') {
console.log('logged out from storage!')
Router.push('/login')
}
}
这些是我们现在注销时需要做的两件事:
取消令牌 在本地存储中设置注销项目
async function logout () {
inMemoryToken = null;
const url = 'http://localhost:3010/auth/logout'
const response = await fetch(url,{
method: 'POST',credentials: 'include',})
// to support logging out from all windows
window.localStorage.setItem('logout',Date.now())
}
view rawlogout2.js hosted with ❤ by GitHub
在这种情况下,只要您从一个标签页中注销,事件监听器就会在所有其他标签页中触发,并将它们重定向到登录屏幕。