nodejs--session&&cookie

作者:烨竹

cookie简介:

cookie 是 http 协议的一部分,它的处理分为如下几步:
服务器向客户端发送 cookie。
通常使用 HTTP 协议规定的 set-cookie 头操作。
规范规定 cookie 的格式为 name = value 格式,且必须包含这部分。
浏览器将 cookie 保存。
每次请求浏览器都会将 cookie 发向服务器。

其他可选的 cookie 参数会影响将 cookie 发送给服务器端的过程,主要有以下几种:
path:表示 cookie 影响到的路径,匹配该路径才发送这个 cookie。
expires 和 maxAge:告诉浏览器这个 cookie 什么时候过期,expires 是 UTC 格式时间,maxAge 是 cookie 多久后过期的相对时间。当不设置这两个选项时,会产生 session cookie,session cookie 是 transient 的,当用户关闭浏览器时,就被清除。一般用来保存 session 的 session_id。
secure:当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。
httpOnly:浏览器不允许脚本操作 document.cookie 去更改 cookie。一般情况下都应该设置这个为 true,这样可以避免被 xss 攻击拿到 cookie。

具体参考:
http://expressjs.com/zh-tw/4x/api.html#res
http://wiki.jikexueyuan.com/project/node-lessons/cookie-session.html
https://blog.csdn.net/kuangshp128/article/details/75152458
https://cnodejs.org/topic/5212d82d0a746c580b43d948

Cookie在express上的应用

首先,我们进入express的官网看到,它提供了几个cookie相关的API参考:
Response (server设定cookie,回传给client)
res.cookie(name,value [,options])
将cookie设置name为value。该value参数可能是一个字符串或对象转换为JSON。
该options参数是一个可以具有以下属性的对象
res.clearCookie(name [,options])清除指定的cookie
Request (向client接收cookie)
req.signedCookies
取得由client端接收过来有设定签章的请求,让它形成未签章并加以使用。
有加上签章的cookie,好处是,只有开发者自己知道的签章加上回应出去给个别oookie时,使用者根本不知道你开发者签了什么,要窜改也难。否则,恶意攻击容易放入req.cookie。

ex.接收过来的Cookie: user= ladykaka .CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
当后面这一串.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3签章与开发人员设定的签章有相应,req.signedCookies.user的值即为: ladykaka

设定签章

express设定签章,必须使用cookie-parser middleware,它的作用是即为cookie做一个签章。
用法:在你的express物件,加入cookieParser(your sign)即可!
参数your sign建议是一个128 bytes的随机字串。

var app=express();
app.use(cookieParser('123456789'));

登陆功能:
建立login文件夹,并且初始化

  mkdir login
    cd login
    npm init  

初始化参数:
package name:你这个Project要叫什么名字
version:你决定这个Project现在该是第几版
description: Project基本介绍
entry point:进入点,如果要跑你的Project应该要执行哪个档案
author:作者(自己)
license:你这个Project是采用什么授权的
test command:这个不太重要,待会会说明

创建相关模块:

    npm install express --save
    npm install body-parser --save
    npm install cookie-parser --save
     npm install pug --save

/public/cookie下建立好静态网页

First name:
Last name:

view下建立pug样板

//index.pug
extends layout

block content
  h1= title
  p hello #{member} 
   if logstatus == false
     a(href="Login.html") 登入
   else
     a(href="./logout") 登出
//layout.pug
doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content
//error.pug
extends layout

block content
  h1= message
  h2= error.status
  pre #{error.stack}

建立express web server

//載入第三方模組
var express = require('express');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
 
//载入路由档案
var routerCookie=require('./routes/loginAPI');
 
var app = express(); //建立一个express物件
 
//set view engine
app.set("view engine","pug")
//set view directory
app.set("views",__dirname+"/views")
 
//將request进來的data 转成 json()
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
 

// Create a router to handle routes for a set of loginAPI
// 抓出來, 变成独立档案
// -------------------------------------------------------
 
//静态档案 like .js, .json, .xml, html....
app.use(express.static(__dirname+'/public'));

 
// 允许 /cookie 使用這個路由
app.use('/cookie', routerCookie);
 
app.listen(3000,function(){
    console.log('Ready...for 3000,二哈!!!');
});

重头戏来了
上方index.js下面的转json数据之后,加入一个签章:

// sign for cookie
app.use(cookieParser('123456789'));

建立路由档案,新建routes文件夹,在下面添加loginAPI.js文件

var express = require("express");
var loginAPI =express.Router();
//进入需要验证的界面
loginAPI.get('/', function(req, res) {
        //一开始预设,所有的登入状态isLogin都是false,预设的登入者是guest。
        //如果,我们接收到的cookie皆存在,则改变登入者姓名及登入状态。
        //然而,无论有没有登入,皆会导到index.jade样版,去做呈现。
    var name='guest';
    isLogin=false;
    if(req.signedCookies.firstName && req.signedCookies.lastName){
        name=req.signedCookies.firstName+ ' '+req.signedCookies.lastName;
         isLogin = true;
         
  }

   res.render('index', { title: 'Express', member:name, logstatus:isLogin });
 }); 
//如果表单送出后,只要fristName, lastName其中一个栏位没有填写,则再重回登入页
//如果都有填了,则可以建立cookie,在/cookie之下有效,使用签章,cookie生存值100分钟。
//建好以后,导向到/cookie即….进入需要验证的页面
loginAPI.post('/post', function(req, res) {
    // ...
    if(req.body.firstName=="" || req.body.lastName=="")
    {
             return res.redirect('Login.html');
    }else{
        res.cookie('firstName', req.body.firstName, { path: '/cookie', signed: true, maxAge:600000});  //set cookie
        res.cookie('lastName', req.body.lastName, { path: '/cookie', signed: true, maxAge:600000 }); //set cookie
        return res.redirect('/cookie');
    }
 });
 

    // 登出...
loginAPI.get('/logout', function(req, res) {
    // ...登出清理cookie,并返回路由、cookie
        res.clearCookie('firstName',{path:'/cookie'});
        res.clearCookie('lastName',{path:'/cookie'});
        return res.redirect('/cookie');
});

module.exports = loginAPI;

做完后
目录结构如下图:

访问效果如下:

session

session store 使用
因为session是储存在server端的,所以,我们可以为Session设置存放位置。
一般而言,session可以存放在:
1.记忆体内存
2.cookie本身
3.redis或memcached等缓存中(常见)
4.数据库中ex. mongoDB。

这边,我将示范,在mongoDB 存session,很简单,只要3个步骤:

  1. 首先,必须先安装express-sessionconnect-mongo (还有更多session储存的API,可以参考 https://github.com/expressjs/session#compatible-session-stores))
  2. 安装好后,我们可以用简单的 计数器程式做例子!首先,引入module:
var session = require('express-session');
const MongoStore = require('connect-mongo')(session);

引入后,在session相关option设置,加入
store:new MongoStore({url:’mongodb://localhost:27017/sessiondb’})
如图:


如此,大功告成!!

在robo 3T查看数据是否增加

登陆
建模:express, express-session, body-parser,connect-mongo这些
在public下添加session文件夹,在添加login.html

First name:
Last name:

index.js

//載入第三方模組
var express = require('express');


// 引入 express-session
var session = require('express-session');
// session store
const MongoStore = require('connect-mongo')(session);


var bodyParser = require('body-parser');
//载入路由档案
var routerSession=require('./routes/loginAPI');
 
var app = express(); //建立一个express物件
 
//set view engine
app.set("view engine","pug")
//set view directory
app.set("views",__dirname+"/views")
 
//將request进來的data 转成 json()
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
 
//設置session相關設定
app.use(session({
    secret: 'recommand 128 bytes random string',
    store:new MongoStore({url:'mongodb://tester:password@localhost:27017/lxkdb'}),
    resave: false,
    saveUninitialized: true,
    cookie: { maxAge: 600 * 1000 } //10分鐘到期
   
  }));
// Create a router to handle routes for a set of loginAPI
// 抓出來, 变成独立档案
// -------------------------------------------------------
 
//静态档案 like .js, .json, .xml, html....
app.use(express.static(__dirname+'/public'));

 
// 允许 /session 使用這個路由
app.use('/session', routerSession);
 
app.listen(3000,function(){
    console.log('Ready...for 3000,二哈!!!');
});

loginAPI.js

var express = require("express");
var loginAPI =express.Router();
//进入需要验证的界面
var isLogin=false;

loginAPI.get('/',function(req,res){
    // 一开始预设,所有的登入状态isLogin都是false,预设的登入者是guest。
//如果,我们接收到的session皆存在,则改变登入者姓名及登入状态。
//然而,无论有没有登入,皆会导到index.jade样版,去做呈现。
//这边与cookie的不同,多了一個測試 進入次數的計數呈現(非必要)
    var name='guest';
    isLogin=false;
    var Logtime=1;
    if(req.session.firstName && req.session.lastName){
        name=req.session.firstName+ ' '+req.session.lastName;
        isLogin = true;
        Logtime= req.session.time;
    }
 
     res.render('index', { title: 'Express', member:name, logstatus:isLogin,time:Logtime });
});

  

loginAPI.post('/post', function(req, res) {
    // 表单送出后,开始进行条件判断。
//如果fristName, lastName其中一个栏位没有填写,则再重回登入页。
//否则,再进行下一个条件判断:只要,两者输入,在session store已有(在未登出情况下,同一笔连线),表示session早已存在,登入次数加1,直接到需要验证的页面即可!– 否则,重新设置session,并导向验证页面。(這裡的判別,可以做省略,主要是為了測試store用!)
    if(req.body.firstName=="" || req.body.lastName=="")
    {
        return res.redirect('Login.html');
    }else if(req.body.firstName==req.session.firstName
             && req.body.lastName==req.session.lastName)
               //如果輸入的,在session store已有儲存..
    {
         req.session.time++; //同一連線的登入次數, 就加 1
         return res.redirect('/session');    //就直接導向到...
    }
    else
    {
        //session store裡沒有的,就會重新設置
        req.session.firstName=req.body.firstName;
        req.session.lastName=req.body.lastName;
        req.session.time=1;
          return res.redirect('/session');
    }
 
});
 

    // 登出...
    loginAPI.get('/logout', function(req, res) {
        //session清空!尔后,导向/session路由, 
        req.session.destroy();
        return res.redirect('/session');
    });

module.exports = loginAPI;

访问如图:


你可能感兴趣的:(nodejs--session&&cookie)