nodejs session 原理及实战

翻译自:https://stormpath.com/blog/ev...前端

clipboard.png

一 Cookie

由于HTTP协议是没有状态的,但不少状况下是须要一些信息的,好比在用户登录后、再次访问网站时,无法判断用户是否登录过。因而就有了cookies,用于在浏览器端保存用户数据,它有以下特色
1 是在客户端浏览器端才有的
2 用于记录信息,大小最大为4K字节
3 若是使用了cookies,那么任何对该域名的访问都会带上cookiesnode

目前新型网站更多的采用浏览器缓存,cookie会存在一些问题,好比你每次往服务器提交请求时,都会带上cookie,不管是你访问的是否是静态图片。数据库

cookie例子:
clipboard.pngexpress

二 Session

session相似服务器端的cookie,保存于服务器端,相似于服务器缓存。用户登录了总须要验证吧,那么就在session中验证便可,session和cookie是一一对应关系。浏览器

session的建立顺序缓存

  1. 生成全局惟一标识符(sessionid);
  2. 开辟数据存储空间。通常会在内存中建立相应的数据结构,但这种状况下,系统一旦掉电,全部的会话数据就会丢失,若是是电子商务网站,这种事故会形成严重的后果。不过也能够写到文件里甚至存储在数据库中,这样虽然会增长I/O开销,但session能够实现某种程度的持久化,并且更有利于session的共享;
  3. 将session的全局惟一标示符发送给客户端。
    问题的关键就在服务端如何发送这个session的惟一标识上。联系到HTTP协议,数据无非能够放到请求行、头域或Body里,基于此,通常来讲会有两种经常使用的方式:cookie和URL重写。

三 Set-Cookie

Cookie是如何被设置的呢?是被服务器返回的请求设置的。安全

clipboard.png

服务器会返回一个set-cookie的消息,通知浏览器要设置cookie了,因而浏览器会根据set-cookie里的字段来设置信息了,好比上图的信息就会设置session=r@rdegges.com服务器

四 实战

咱们以client-session(express-session基本彻底同样)为例,为项目配置session
1 安装模块cookie

var session = require('client-sessions');

2 配置session网络

app.use(session({
  cookieName: 'session',
  secret: 'random_string_goes_here',
  duration: 30 * 60 * 1000,
  activeDuration: 5 * 60 * 1000,
}));

1)secret:一个随机字符串,由于客户端的数据都是不安全的,因此须要进行加密
2) duration:session的过时时间,过时了就必须从新设置
3) activeDuration: 激活时间,好比设置为30分钟,那么只要30分钟内用户有服务器的交互,那么就会被从新激活。

五 在Session中保存用户信息

app.post('/login', function(req, res) {
  User.findOne({ email: req.body.email }, function(err, user) {
    if (!user) {
      res.render('login.jade', { error: 'Invalid email or password.' });
    } else {
      if (req.body.password === user.password) {
        
        // sets a cookie with the user's info
        req.session.user = user;
        // 这里貌似有误,只是set了session,返回这个sessionid,但但数据并不会set到这个cookie里头
        
        res.redirect('/dashboard');
      } else {
        res.render('login.jade', { error: 'Invalid email or password.' });
      }
    }
  });
});

六 Session层中间件

咱们固然不但愿每一个请求都加上这一段,因此咱们使用express来作全局配置

app.use(function(req, res, next) {
  if (req.session && req.session.user) {
    User.findOne({ email: req.session.user.email }, function(err, user) {
      if (user) {
        req.user = user;
        delete req.user.password; // delete the password from the session
        req.session.user = user;  //refresh the session value
        res.locals.user = user;
      }
      // finishing processing the middleware and run the route
      next();
    });
  } else {
    next();
  }
});

若是用户逻辑在没有登录时必须登录,那咱们能够继续加一个路由

function requireLogin (req, res, next) {
  if (!req.user) {
    res.redirect('/login');
  } else {
    next();
  }
};

app.get('/dashboard', requireLogin, function(req, res) {
  res.render('dashboard.jade');
});

七 安全性

1 咱们能够在登出时重置session

app.get('/logout', function(req, res) {
  req.session.reset();
  res.redirect('/');
});

还能够加一些安全性
httpOnly:用来保证cookie只能经过http访问,而不能用js来读取
secure:强制使用https
ephemeral:关闭浏览器时同时关闭cookie

八 总结

Cookie和session因为实现手段不一样,所以也各有优缺点和各自的应用场景:

  1. 应用场景
    Cookie的典型应用场景是Remember Me服务,即用户的帐户信息经过cookie的形式保存在客户端,当用户再次请求匹配的URL的时候,帐户信息会被传送到服务端,交由相应的程序完成自动登陆等功能。固然也能够保存一些客户端信息,好比页面布局以及搜索历史等等。

Session的典型应用场景是用户登陆某网站以后,将其登陆信息放入session,在之后的每次请求中查询相应的登陆信息以确保该用户合法。固然仍是有购物车等等经典场景;

  1. 安全性
    cookie将信息保存在客户端,若是不进行加密的话,无疑会暴露一些隐私信息,安全性不好,通常状况下敏感信息是通过加密后存储在cookie中,但很容易就会被窃取。而session只会将信息存储在服务端,若是存储在文件或数据库中,也有被窃取的可能,只是可能性比cookie小了太多。

Session安全性方面比较突出的是存在会话劫持的问题,这是一种安全威胁,这在下文会进行更详细的说明。整体来说,session的安全性要高于cookie;

  1. 性能
    Cookie存储在客户端,消耗的是客户端的I/O和内存,而session存储在服务端,消耗的是服务端的资源。可是session对服务器形成的压力比较集中,而cookie很好地分散了资源消耗,就这点来讲,cookie是要优于session的;
  2. 时效性
    Cookie能够经过设置有效期使其较长时间内存在于客户端,而session通常只有比较短的有效期(用户主动销毁session或关闭浏览器后引起超时);
  3. 其余
    Cookie的处理在开发中没有session方便。并且cookie在客户端是有数量和大小的限制的,而session的大小却只以硬件为限制,能存储的数据无疑大了太多。

咱们建了个前端自助学习QQ群,面向-1-2年码农,有兴趣的不妨加入:370423482


继续补充下,关于如何作一个完整的登录

1 用户端

通常来讲应该使用https,并且密码毫不能在网络中明文传输,所以在往服务器传输时就应该先加密,常见的md5,但md5被破解,所以能够用SHA512来加密 SHA256(password)

2 服务端

服务端须要对密码再进行加密,由于全部客户端的东西都是不安全的,万一你的网络被监听了呢,所以会进行 SHA512(username+SHA512(password)+sault)的加密,这里的sault为随机数,防止被脱库了后被猜出密码,因此须要附加一个随机数,这个sault最好是存放到另外的数据库中,防止由于存到一个库中被脱库中猜出

累了,有空再加

相关文章
相关标签/搜索