我们来做一个使用cookie和seesion保持网站持久登录的例子,来让我们了解在node是如何使用他们的
1.初始化项目
我们使用express项目生成器生成一个项目:
$express -e cookie
$cd cookie
$npm install
使用cookie需要 cookie-parser中间件,我们的express生成的项目中已经帮我们配置好了。
2.新增页面
项目创建好之后,打开views文件夹 创建login.ejs页面,以及修改index.ejs页面。
登录页面:
login.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title登录</title>
<style>
p{color: red}
</style>
</head>
<body>
<form action="login" method="post">
<%if(typeof(error) !== 'undefined' && error){%>
<p><%= error %></p>
<% } %>
用户名:<input type="text" name="username" ><br/>
密码:<input type="password" name="pwd" ><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
主页面:
index.ejs
<!DOCTYPE html>
<html>
<head>
<title>主页</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<%if(typeof(user) !== 'undefined' && user){%>
<h1>Welcome <%= user.username %>, 欢迎登录!!</h1>
<a claa="btn" href="/logout">退出</a>
<%}else{%>
<h1>Welcome , <a claa="btn" href="/login">请登录!!</a></h1>
<%}%>
</body>
</html>
当存在cookie的时候显示用户名,退出则销毁cookie。
当不存在cookie的时候告诉用户进行登录。
3.修改逻辑
修改index.js
我们添加了一个login页面,那么我们肯定需要相应的路由来渲染该页面
添加login路由:
router.get('/login', function (req,res,next){
res.render('login')
})
同理,添加index路由:
router.get('/index', function(req, res, next) {
res.render('index');
});
$npm start
OK ,虽然丑陋了一点。
接下来我们处理一下逻辑 。
我们需要处理一个表单提交的逻辑,如果用户名和密码争取则进入主页,如果错误则提示错误信息。
增加路由:
router.post('/login', function (req,res,next){
var username = req.body.username;
var pwd = req.body.pwd;
var user={
username:'admin',
pwd:123456
}
if(username==user.username && pwd==user.pwd){
//设置cookie
res.cookie("user", {username: username}, {maxAge: 600000 , httpOnly: false});
res.redirect('index');
}else{
req.error = '用户名密码错误'
res.render('login' , req) ;
}
})
如果用户名和密码正确则设置一个cookie user
我们把用户名存入cookie中
maxAge 为客户端保存cookie多长时间,单位是毫秒,如果省略这个选项,那么浏览器关闭时 cookie就会被删掉。
httpOnly 当这个选项为true时候,表明这个cookie只能有服务器修改,也就是说不能使用js修改他,这个有助于防范xss攻击。
我们设置了cookie当然需要使用它了
修改index路由
router.get('/index', function(req, res, next) {
if(req.cookies.user !== null){
req.user=req.cookies.user;
}
res.render('index', req);
});
存在user这个cookie时候,把该cookie挂载在req.user中 ,这样我们在前台可以使用它。
我们还需要一个退出功能,增加路由
router.get('/logout', function (req,res,next){
//删除Cookie
res.clearCookie('user');
res.redirect('index');
})
index.js完整代码
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/index', function(req, res, next) {
if(req.cookies.user !== null){
req.user=req.cookies.user;
}
console.log(req.user)
res.render('index', req);
});
router.get('/login', function (req,res,next){
res.render('login')
})
router.post('/login', function (req,res,next){
var username = req.body.username;
var pwd = req.body.pwd;
var user={
username:'admin',
pwd:123456
}
if(username==user.username && pwd==user.pwd){
res.cookie("user", {username: username}, {maxAge: 600000 , httpOnly: false});
res.redirect('index');
}else{
req.error = '用户名密码错误'
res.render('login' , req) ;
}
})
router.get('/logout', function (req,res,next){
//删除Cookie
res.clearCookie('user');
res.redirect('index');
})
module.exports = router;
4.项目预览
5.httpOnly
当httpOnly为false 时候我们可以通过js修改它的cookie,
我们在控制台输入document.cookie="users="+123;
刷新页面,可以看到 多了一个users cookie,
同理我们也可以修改user的cookie,这是很不安全的。
当httpOnly为true的时候,我们发现不能这样修改cookie,所以这个httpOnly有助于防范xxs攻击
通常我们会设置一个包含唯一标识的cookie,然后服务器通过这个标识来获取相应的seesion。
seesion和cookie十分的相似,但是seesion是把信息存储在服务器上,而cookie是把信息存储在客户端,也就是本地。
5.session
使用session我们需要 express-session 中间件
$npm install express-session --save
注意:1.5.0版本之前该中间件需要依赖 cookie-parser,在这之后是不需要cookie-parser的,如果依赖了可能会报错的
因为我们是1.5.0之后的版本,所以我们修改app.js
<pre name="code" class="javascript">
</pre><pre name="code" class="javascript">//第5行
var cookieParser = require('cookie-parser');
//修改为
var session = require('express-session');
//第22行修改
app.use(cookieParser());
//修改为
app.use(session({secret:'test',name:"user" ,cookie:{maxAge: 6000 } }));
其中
secret:用来对session数据进行加密的字符串.这个属性值为必须指定的属性。name:表示cookie的name,默认cookie的name是:connect.sid。maxAge:cookie过期时间,毫秒。resave:是指每次请求都重新设置session cookie,假设你的cookie是6000毫秒过期,每次请求都会再设置6000毫秒。saveUninitialized: 是指无论有没有session cookie,每次请求都设置个session cookie ,默认给个标示为 connect.sid。
修改index.js:
var express = require('express');
var router = express.Router();
router.get('/index', function(req, res, next) {
if(req.session.user!== null){
req.user=req.session.user;
}
console.log(req.user)
res.render('index', req);
});
router.get('/login', function (req,res,next){
res.render('login')
})
router.post('/login', function (req,res,next){
var username = req.body.username;
var pwd = req.body.pwd;
var user={
username:'admin',
pwd:123456
}
if(username==user.username && pwd==user.pwd){
req.session.user = {username:username,pwd:123456};
res.redirect('index');
}else{
req.error = '用户名密码错误'
res.render('login' , req) ;
}
})
router.get('/logout', function (req,res,next){
//删除Cookie
delete req.session.user;
res.redirect('index');
})
module.exports = router;
OK,我们完成了使用session持久登录。
6.其他
上面的session使用是把信息存在内存中,这样有很多缺陷,比如说在我们重启服务的时候,会发现session消失了。
有时候我们会想让登录信息保持很久,那么我们存在内存中也是不太好的选择。
我们可以把信息存储在数据库中,mongodb和redis是很好的选择。个人推荐redis。
具体的把信息存储在数据库中本文不涉及暂时不涉及。