Cookie、session和拦截器-实现登录认证

1、cookie技术

1. 什么是cookie
说起来,Cookie应该是一种应用较久的技术了。早在HTML刚刚出现的时候,在每个独立的页面之间没有办法记录和标识不同的用户。后来人们就发明了 Cookie技术,当用户访问网页时,它能够在访问者的机器上创立一个文件,我们把它叫作Cookie,写一段内容进去,来标识不同的用户。如果下次用户再访问这个网页的时候,它又能够读出这个文件里面的内容,这样网页就知道上次这个用户已经访问过该网页了。
简言之cookie是web服务器保存在客户端的一系列文本信息.
2、cookie作用
1.对特定对象的追踪. 商城网站记录购物者浏览对象。
2.保存用户网页浏览记录与习惯。
3.简化登录。
3、浏览器查看cookie
crome浏览器
打开Chrome
1.进入Chrome设置
2.找到【隐私设置】
3.进入【内容设置】
在这里插入图片描述在这里插入图片描述在这里插入图片描述4.cookie-parser中间件

ame=value:键值对,可以设置要保存的 Key/Value,注意这里的 name 不能和其他属性项的名字一样
Expires: 过期时间(秒),在设置的某个时间点后该 Cookie 就会失效,如 expires=Wednesday, 09-Nov-99 23:12:40 GMT
maxAge: 最大失效时间(毫秒),设置在多少后失效
secure: 当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效
Path: 表示 cookie 影响到的路,如 path=/。如果路径不能匹配时,浏览器则不发送这个Cookie
npm install cookie-parser;

var cookie = require('cookie-parser');

app.use(cookie()); // 引cookie中间件

发cookie信息到客户端

res.cookie('user', 'admin' ,  //名称,值
{
maxAge: 1000 * 60 * 60,
expires: '2020-1-1',
path: '/',
secure: false,
});

获取保存在客户端的cookie信息
req.cookies.cookie-name
清除cookie
res.clearCookie(cookie-name);
5. 实现记住密码-cookie
在这里插入图片描述

/*
* 登录提交
*/
userRouter.post('/login.do', function (req, res, next) {
var userName = req.body.name;
var passWord = req.body.password;
var autoLogin = req.body.autoLogin;

var sql = 'SELECT id,username,password FROM user WHERE username = ? AND password = ?';
var parameters = [userName, passWord];
querydb(sql, parameters)
.then(function (data) {
if (data.length === 0) {
res.render('login', {
'message': '用户名或密码出错!',
});
} else {
// 登陆成功后将用户和密码写入Cookie,maxAge为cookie过期时间
if (autoLogin === 'on') {
res.cookie('user', {
'username': req.body.name,
'password': req.body.password,
}, {
maxAge: 1000 * 60 * 60,
});
} else {
// 删除cookie
res.clearCookie('user');
}
res.redirect('/main.do');
}
}).catch(next);
});
/**
* 登录界面
*/
userRouter.get('/', function (req, res) {
if (req.cookies.user) {
res.render('login', {
'user': {
'username': req.cookies.user.username,
'password': req.cookies.user.password,
},
});
} else {
res.render('login');
}

});
<form action="login.do" method="post" enctype="application/x-www-form-urlencoded">
<h1>后台管理中心</h1>
<div >
<input type="text"  name="name" placeholder="登录账号" value="<%= locals.user != null?user.username:'' %>"/>
</div>
<div >
<input type="password" name="password" placeholder="登录密码"value="<%= locals.user != null?user.password:'' %>" />
</div>
<div >
<input type="checkbox" name="autoLogin" checked> 记住密码
</div>
<div style="color: red;"> <%= locals.message !=null?message:'' %></div>
<div>
<input type="submit" value="登录">
</div>
</form>

6. 抓包查看cookie
在这里插入图片描述

2、session技术

1.什么是session
在这里插入图片描述在这里插入图片描述
2.理解session
Session是在客户端请求到达服务器时,服务器为此请求发出的客户所创建的一个对象,保存在服务器端。购物车是一个很好的例子,一个用户可以有很多session,但每个session只针对一个用户,这就保证了不同session之间的信息独立。
首先说明一点,在通常意义上,session所能发挥作用是基于cookie机制。针对所需要解释的问题,做这样一个假设:我们第一次访问一个网页。当客户端发送请求后,服务端会建立一个针对此请求发出客户的session对象,而且每个session都会有一个sessionID。服务端会自动将这个sessionID作为一个cookie附加到response上返回给客户端,这个cookie存放在浏览器内存中。我们每次对此网页发送的request都会附带着这个cookie,服务端收到这个请求后会都去cookie中取得这个sessionID,然后查询服务端是否存在一个对应此ID的session对象。如果有,可以直接使用此session;如果没有,则会新建一个。当浏览器关闭后,其所占的内存就会是放掉,cookie自然也就被清除了,此时我们不再保存有这个sessionID。所以再打开浏览器访问同一个页面时,由于没有sessionID,也就查不到对应的session对象,此时重新创建一个新的session对象。
那当我们关闭浏览器之后,服务器端原来的session对象是否还存在呢?答案是肯定的。服务端根本不知道我们是否关闭了浏览器,也不关心这个。客户端与服务端之间进行通信的唯一途径就是通过请求。服务器有自己的一套机制来管理session,比如多长时间会清除没有使用过的session对象,等等。
所以说,关闭浏览器session就被清除只是我们所看到的表面现象(实际上是新建了一个session对象),通常情况下,服务器并不会马上清除session对象,但这个根据服务端的设定而不同。
PS:cookie一般分为两种:一种是会话cookie,即服务端为session自动创建的cookie,这个cookie存放在浏览器进程中。另一种是可以存放在硬盘上的,可以通过服务端的某些设置,将一些信息放到cookie中并返回给客户端存放在硬盘上。
3.express-session中间件
express-session中间件将会话数据存储在服务器上;它仅将会话标识(而非会话数据)保存在 cookie 中。从1.5.0版本开始, express-session不再依赖cookie-parser,直接通过req/res读取/写入;默认存储位置内存存储(服务器端),
安装: npm install express-session

var session = require('express-session');
// 引入session中间件
app.use(session({ // 这里的name值得是cookie的name,默认cookie的name是:connect.sid
name: 'web1803',
secret: 'websecret',
cookie: ({
maxAge: 1000 * 60 * 60 * 24,
}),
// 重新保存:强制会话保存即使是未修改的。默认为true但是得写上
resave: true,
// 强制“未初始化”的会话保存到存储。
saveUninitialized: true,

}));

主要方法 : session(options)
通过option来设置session存储,除了session ID外,session中的任何数据都不存储在cookie中。
options可选参数:

name - cookie的名字( 原属性名为 key)。( 默认:’ connect.sid’)
store - session存储实例
secret - 用它来对session cookie签名, 防止篡改
cookie - session cookie设置( 默认: { path: ‘ /‘, httpOnly: true,secure: false, maxAge: null })
genid - 生成新session ID的函数( 默认使用uid2库)
rolling - 在每次请求时强行设置cookie, 这将重置cookie过期时间( 默认: false)
resave - 强制保存session即使它并没有变化( 默认: true)
proxy - 当设置了secure cookies( 通过” x - forwarded - proto” header) 时信任反向代理。 当设定为true时,” x - forwarded - proto” header 将被使用。 当设定为false时, 所有headers将被忽略。 当该属性没有被设定时, 将使用Express的trust proxy。
saveUninitialized - 强制将未初始化的session存储。 当新建了一个session且未设定属性或值时, 它就处于未初始化状态。 在设定一个cookie前, 这对于登陆验证, 减轻服务端存储压力, 权限控制是有帮助的。( 默认: true)
unset - 控制req.session是否取消( 例如通过 delete, 或者将它的值设置为null)。 这可以使session保持存储 状态但忽略修改或删除的请求( 默认: keep)

express-session的一些方法:

1. Session.destroy():删除session,当检测到客户端关闭时调用。
2. Session.reload():当session有修改时,刷新session。
3. Session.regenerate():将已有session初始化。
4. Session.save():保存session。

4.登录权限验证

// 保存登录状态到session
req.session.user = userName;


/**
* 主界面
*/
userRouter.get('/main.do', function (req, res, next) {
console.log('req.session.user :' + req.session.user);
if (req.session.user) {
res.render('index', {
'title': '主界面',
'name': '首页',
});
} else {
res.redirect('/'); // 重定向到登录界面
}
});



/**
* 退出
*/
userRouter.get('/logout.do', function (req, res, next) {
req.session.destroy(); // 销毁session
res.redirect('/');
});

3、cookie与session区别

在这里插入图片描述

4、重定向redirect传参与flash一起使用

flash方法在express 3.X的时候分离出去了,现在使用需要引用connect-flash模块,且只能放在session模块引用下面。
使用时先设置session,然后在路由前设置flash,

var flash = require('connect-flash');

// 设置flash,这步要在路由之前
userRouter.use(flash());
/**
* 主界面
*/
userRouter.get('/main.do', function (req, res, next) {
// 判断session 状态,如果有效,则返回主页,否则转到登录页面
if (req.session.username) {
res.render('index', {
'title': '主界面',
'name': '首页',
});
} else {
req.flash('message', '你还没有登录'); // 保存信息
//req.session.msg = '您还没有登录,请登录11!';
res.redirect('/');
}
});

/**
* 登录界面
*/
userRouter.get('/', function (req, res) {
var msg = req.flash('message'); // 获取信息之后销毁session中message对象
//var msg = req.session.msg;
console.log('msg :' + msg);
res.render('login', {
'message': msg,
'user': {
'username': req.cookies.user.username,
'password': req.cookies.user.password,
},
});
});

5、四大对象 - app.locals与res.locals

                              生命周期
Application对象         web服务器启动时创建             服务器停止时结束                var app  = express();   app.set(name,value);  var value = app.get(name);
Session对象             第一次http请求时创建            关闭浏览器时 | 退出程序 session.destory() session时间到期结束     var sess = req.session;  sess.name = value;   var value = sess.name;
Request对象             发送请求时创建,请求结束销毁     请求行, 头部,正文
Response对象            响应时创建,响应结束销毁         响应行,头部,正文

Application####
app对象一般是Express应用程序,通过使用入口函数express()导出

var express=require("express");
var app=express();

app.get("/",function(req,res){
    res.send("hello world");
});
app.listen(3000);

app对象有处理以下事务的一些方法:
• 处理http请求的路由:请看app.METHOD和app.param
• 配置中间件:请看app.route
• 渲染HTML视图:请看app.render
• 设置模板引擎:请看app.engine
app同样可以设置一些影响app工作的属性,获取更多信息,请看Application settings
属性#####
app.locals
app.locals对象是一个JavaScript对象,并且它的属性是应用程序的本地变量
app.locals.title
// =>“My App”

app.locals.email
// =>"me@myapp.com"
一旦设置了app.locals的属性,这个属性就会存在于应用程序的整个生命周期,二而不同于res.locals设置的属性只存在请求的生命周期中
你可以在应用程序的模板中使用本地变量,这对于模板和应用级数据来说提供了很有用的辅助功能,但是你在中间件中并不能访问本地变量
• app.locals.title=“My App”;
• app.locals.strftime=require(“strftime”);
app.locals.email="me@myapp.com";

res.locals.name = '首页';
if (req.session.user) {
res.render('index', {
'title': '主界面',
// 'name': '首页',
});
} 

在调用 res.render 的时候,express 合并(merge)了 3 处的结果后传入要渲染的模板,优先级:res.render 传入的对象> res.locals 对象 > app.locals 对象,所以 app.locals 和 res.locals 几乎没有区别,都用来渲染模板,使用上的区别在于:app.locals 上通常挂载常量信息(如博客名、描述、作者信息),res.locals 上通常挂载变量信息,即每次请求可能的值都不一样(如请求者信息,res.locals.user = req.session.user)。

6、统一登录认证-拦截器

/**
* 统一登录认证--拦截
*/
userRouter.all('/*', function (req, res, next) {
console.log('登录认证拦截 url : ' + req.url);
// url处理方式一
// var arr = req.url.split('/'); // 解析用户请求的路径
// for (var i = 0, length = arr.length; i < length; i++) { // 去除 GET 请求路径上携带的参数
// arr[i] = arr[i].split('?')[0];
// }
// if (arr.length > 1) {
// if (arr[1] === 'login.do' || arr[1] === 'logout.do' || arr[1] === 'register.do') {
// next();
// } else {
// logger.error('intercept:用户未登录执行登录拦截,路径为:' + arr[1]);
// res.redirect('/maindo'); // 将用户重定向到登录页面
// res.end();
// }
// }

// url处理方式二
var reqUrl = req.url + ''; // 对象转字符串 /user/list/main.do?username=admin
if (reqUrl.indexOf('?') !== -1) { // 判断reqUrl有没有?,如果没有返回-1
reqUrl = reqUrl.substring(0, reqUrl.lastIndexOf('?')); // /main.do
}
console.log('Url :' + reqUrl);
// 指定请求放行
if (reqUrl.endsWith('login.do') || reqUrl.endsWith('logout.do') || reqUrl.endsWith('/') || reqUrl === '') {
next();
} else {
if (req.session.user) { // 登录认证
next();
} else {
req.session.originalUrl = req.originalUrl; // 保存原始请求url地址到session中
req.flash('msg', '您还没有登录,请登录!');
res.redirect('/'); // 重定向到登录界面
}
}
});
/*
* 登录提交 
*/
userRouter.post('/login.do', function (req, res, next) {
var userName = req.body.name;
var passWord = req.body.password;
var autoLogin = req.body.autoLogin;

var sql = 'SELECT id,username,password FROM user WHERE username = ? AND password = ?';
var parameters = [userName, passWord];
querydb(sql, parameters)
.then(function (data) {
if (data.length === 0) {
res.render('login', {
'message': '用户名或密码出错!',
});
} else {
// 判断是否需要记住密码
if (autoLogin === 'on') {
res.cookie('user', {
'username': userName,
'password': passWord,
}, {
maxAge: 1000 * 60 * 60 * 24, // cookie信息保存一天
});
} else {
res.clearCookie('user'); // 清除cookie
}
// 保存登录状态到session
req.session.user = userName;
// req.app.user = userName;

//-----实现登录后跳转到原始请求页面----
var redirectUrl = '/main.do';
if (req.session.originalUrl) {
redirectUrl = req.session.originalUrl;
req.session.originalUrl = null;
}
// 重定向到主界面
res.redirect(redirectUrl);
}
})
.catch(next);
});
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值