[英]Express session is not working with “Error: Can't set headers after they are sent.”
我正在嘗試為我的node js應用程序提供身份驗證,為此我使用express-session npm,基本上是在/ login頁面中我的憑據正確時嘗試的,它應該啟動會話並將我帶到/ admin頁面。這樣,/ admin可以在其他選項卡中直接訪問一段時間。當我單擊注銷按鈕時,應該帶我到主頁,應該取消會話,並且不應該直接訪問/ admin頁面並重定向到/ login。頁。
登錄成功后,我嘗試啟動會話,但是它給了我錯誤:發送標頭后無法設置標頭。
app.js
var session = require('express-session');
app.use(session({
secret: 'securedsession',
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
resave: true,
saveUninitialized: true,
maxAge: new Date(Date.now() + 3600000)
}
}));
var auth = function(req, res, next) {
if (req.session && req.session.user === "admin" && req.session.admin)
return next();
else
return res.sendStatus(401);
};
app.post('/verifylogin', function(req, res) {
var username = req.headers.uname;
var password = req.headers.pwd;
if (!username || !password) {
res.send('login failed');
} else if (username === "admin" || password === "adminnn") {
req.session.user = "admin";
req.session.admin = true;
res.contentType('application/json');
var data = JSON.stringify('/admin');
res.header('Content-Length', data.length);
res.send(data);
}
app.get('/logout', function(req, res) {
req.session.destroy();
res.send("logout success!");
});
app.get('/admin', auth, function(req, res, next) {
res.sendFile(__dirname + '/public/views/admin.html');
});
login.html
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
function login() {
var uname = document.getElementById('uname').value;
var pwd = document.getElementById('pwd').value;
$.ajax({
url: '/verifylogin',
type: "POST",
headers: {
"uname": uname,
"pwd": pwd
},
success: function(data) {
window.location = data;
}
});
}
</script>
<h1>Login</h1>
<p>
<label class="control-label">Username</label>
<input type="text" placeholder="Username" id="uname" />
</p>
<p>
<label class="control-label">Password</label>
<input type="password" placeholder="Password" id="pwd" /><br/>
</p>
<p>
<button type="submit" class="btn btn-primary" onclick="login()">Login</button>
</p>
有人可以幫我解決我在這里遇到的錯誤以及如何解決此問題並開始會議
*********編輯
建議后的最新代碼,即使信用證明是正確的,也將我重定向到未經授權的地方,而不是/ admin。可以看看嗎?
app.js
var app = express();
var d = new Date();
app.use(methodOverride());
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(session({
secret: 'securedsession',
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
resave: true,
saveUninitialized: true,
maxAge: d.getTime() + 10
}
}));
app.set('view engine', 'pug');
app.post('/verifylogin', function(req, res) {
var username = req.body.uname;
var password = req.body.pwd;
var uname = "admin";
var pwd = "admin@123";
if (uname == username && pwd == password) {
console.log("success");
req.session.user = "admin";
req.session.admin = true;
req.session.save();
console.log("resdasdasda", req.session);
res.contentType('application/json');
var data = JSON.stringify('/admin');
res.header('Content-Length', data.length);
res.send(data);
} else {
console.log("fail");
res.send("Bad luck");
}
});
var auth = function(req, res, next) {
if (req.session && req.session.user === "admin" && req.session.admin)
return next();
else
return res.sendStatus(401);
};
app.get('/', function(req, res, next) {
res.sendFile(path.join(__dirname + '/public/views/home.html'));
});
app.get('/login', function(req, res, next) {
res.sendFile(__dirname + '/public/views/login.html');
});
app.get('/admin', auth, function(req, res, next) {
res.sendFile(__dirname + '/public/views/admin.html');
});
app.get('/logout', function(req, res) {
req.session.destroy();
res.send("logout success!");
});
module.exports = app;
html
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
function login() {
var uname = document.getElementById('uname').value;
var pwd = document.getElementById('pwd').value;
$.ajax({
url : '/verifylogin',
type : "POST",
data : {
"uname":uname,
"pwd" :pwd
},
success: function(data) {
window.location = data;
}
});
}
</script>
<h1>Login</h1>
<p>
<label class="control-label">Username</label>
<input type="text" placeholder="Username" id="uname" />
</p>
<p>
<label class="control-label">Password</label>
<input type="password" placeholder="Password" id="pwd" /><br/>
</p>
<p>
<button type="submit" class="btn btn-primary" onclick="login()">Login</button>
</p>
當您對同一請求有多個res.send()
,將導致報告錯誤。 因此,您正在代碼中尋找可能導致這種情況的東西。
當您適當縮進部分代碼時,它看起來像這樣:
app.post('/verifylogin', function (req, res) {
var username = req.headers.uname;
var password = req.headers.pwd;
if (!username || !password) {
res.send('login failed');
} else if (username === "admin" || password === "adminnn") {
req.session.user = "admin";
req.session.admin = true;
res.contentType('application/json');
var data = JSON.stringify('/admin');
res.header('Content-Length', data.length);
res.send(data);
}
app.get('/logout', function (req, res) {
req.session.destroy();
res.send("logout success!");
});
});
這意味着您在app.get()
內部有一個app.post()
,這永遠不是正確的方法。 這將導致安裝多個app.get('/logout')
處理程序,因此您將嘗試對/ logout請求多次執行res.send()
。
應該是這樣的:
app.post('/verifylogin', function (req, res) {
var username = req.headers.uname;
var password = req.headers.pwd;
if (!username || !password) {
res.send('login failed');
} else if (username === "admin" || password === "adminnn") {
req.session.user = "admin";
req.session.admin = true;
res.contentType('application/json');
var data = JSON.stringify('/admin');
res.header('Content-Length', data.length);
res.send(data);
}
});
app.get('/logout', function (req, res) {
req.session.destroy();
res.send("logout success!");
});
根據您的修改,建議您通過更改以下內容來保存會話,從而避免出現任何競爭狀況:
app.post('/verifylogin', function(req, res) {
var username = req.body.uname;
var password = req.body.pwd;
var uname = "admin";
var pwd = "admin@123";
if (uname === username && pwd === password) {
console.log("success");
req.session.user = "admin";
req.session.admin = true;
req.session.save(() => {
console.log("resdasdasda", req.session);
res.json(data);
});
} else {
console.log("fail");
res.send("Bad luck");
}
});
除此之外,我想到的唯一會導致您丟失會話的其他事情就是瀏覽器丟失了會話Cookie。 您可以在瀏覽器端通過檢查Chrome調試器中的“網絡”標簽並查看是否已將所需的會話Cookie與/admin
的請求一起發送來檢查。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.