服务端和客户端的cookie传递

一、现象

CSDN的登录界面下会有“两周内不再登录”选项,用户登录后会保存用户登录信息,第二次登录时自动补全登录密码

二、过程

1、当客户端发送一个请求的时候,会产生一个request对象,这个对象里面就包含了cookie
2、服务端先设置cookie信息,并在客户端请求时把这个cookie信息发送给客户端,客户端会自动保存cookie的key/value值
3、下次向服务端发送请求时,客户端会自动带上cookie信息,服务端会根据cookie信息来识别状态。(之前是否访问过)
4、简单说就是在客户端,保存一串加密后的字符串,下次用户访问时,获取这个加密串进行解密匹配,然后创建登录Session信息。

三、定义

cookie用来给无状态的http请求增添状态标记,供服务端辨识,也称客户端缓存.
服务端和客户端的cookie是同一个东西,都是保存在浏览器的,服务端常用的方式是存在session里

  • http 是一种无状态协议,浏览器请求服务器是无状态的
  • 无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。
  • 无状态原因:浏览器与服务器是使用 socket 套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket 连接,而且服务器也会在处理页面完毕之后销毁页面对象

cookie的结构

key:cookie的名称
value:cookie的值
expires:cookie的失效日期(UTC时间字符串)
max-age:cookie的失效间隔(秒),优先级高于expires
path:根据目录限制cookie的分享,如不主动设置,默认为当前页面的路径
domain:根据域名限制cookie的分享

cookie的分类

一、客户端

可以设置、更改、删除cookie

function getCookie(name) {
    var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    if (arr = document.cookie.match(reg))
      return (arr[2]);
    else
      return null;
  }
  
 
function setCookie (c_name, value, expiredays) {
    var exdate = new Date();
    exdate.setDate(exdate.getDate() + expiredays);
    document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
  };
  
 
function delCookie (name) {
    var exp = new Date();
    exp.setTime(exp.getTime() - 1);
    var cval = getCookie(name);
    if (cval != null)
     document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
  };

以用户登录为例,可以存用户登录的用户名和密码(或者代表用户信息的其他格式)
当下次访问网页的时候,直接读取这些信息,发送到服务端去进行验证

二、 服务端

express可以利用第三方组件cookie-parser去进行解析客户端来的req.cookies,也可以在返回信息给客户端的时候设置cookie,这样客户端在接受到这些信息的时候,就会将cookie信息自动保存到硬盘cookie里面,跟在客户端自己保存一样,不过要在客户端和服务器端做一下特殊的设置。

// express
var express      = require('express');
var cookieParser = require('cookie-parser');
 
var app = express();
app.use(cors({
    //credentials: true,//如果需要跨域那么需要设置这两个属性,表示服务器端接受这个域来的信息
    //origin: 'http://localhost:8080'
}))
app.use(cookieParser());
 
app.get('/', function (req, res) {
    // 检查 session 中的 isVisit 字段是否存在
    // 如果存在则增加一次,否则为 session 设置 isVisit 字段,并初始化为 1。
    if (req.cookie.isVisit) {
        req.cookie.isVisit++;
        res.send('<p>第 ' + req.cookie.isVisit + '次来此页面</p>');
    } else {
        req.cookie.isVisit = 1;
        res.send("欢迎第一次来这里");
        console.log("Cookies: ", req.cookies); //打印cookie
    }
});
app.listen(80);

在进行这些初始化之后就可以进行调用函数进行设置/清除cookies

//node, express
app.get('/test', function(req, res, next) {
    res.cookie(key,value,{
        maxAge:1000,//毫秒为单位,
        //domain
        //path
        httpOnly:boolean,//设置为true,客户端无法查看、更改,仅作为发送至服务端的凭据
    })
    //不设置表示无期限
    res.cookie(key,value)
})
//res.cookie(name, value [, options]);  //设置cookies, options可以设置很多参数。
//res.clearCookie(name [, options]);   //清除cookies,

当然服务端读取cookie的时候,直接利用req.cookies或者req.signedCookies来读取参数信息

但是一般情况下服务端的cookie存放在session来处理。来个示例:

//session
var express = require('express');
var session = require('express-session');
var app = express();

app.use(session({
    secret: 'zsshua app', //secret的值建议使用随机字符串
    cookie: {maxAge: 60 * 1000 * 30} // 过期时间(毫秒)
}));
app.get('/', function (req, res) {
    if (req.session.sign) {//检查用户是否已经登录
        console.log(req.session);//打印session的值
        res.send('welecome <strong>' + req.session.name + '</strong>, 欢迎你再次登录');
    } else {//否则展示index页面
        req.session.sign = true;
        req.session.name = '我的网站';
        res.end('欢迎登录!');
    }
});
app.listen(80);

express

//app.js中添加如下代码(已有的不用添加)
var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');

app.use(cookieParser('sessiontest'));
app.use(session({
    secret: 'sessiontest',//与cookieParser中的一致
    resave: true,
    saveUninitialized:true
}));
//修改router/index.js,第一次请求时我们保存一条用户信息。
router.get('/', function(req, res, next) {
    var user={
        name:"Chen-xy",
        age:"22",
        address:"bj"
    }
  req.session.user=user;
  res.render('index', {
      title: 'the test for nodejs session' ,
      name:'sessiontest'
  });
});
//修改router/users.js,判断用户是否登陆。
router.get('/', function(req, res, next) {
    if(req.session.user){
        var user=req.session.user;
        var name=user.name;
        res.send('你好'+name+',欢迎来到我的网站。');
    }else{
        res.send('你还没有登录,先登录下再试试!');
    }
});

跨域问题

客户端发送http请求是会携带cookie(凭证)到服务端。同样遵循同源策略,会遇到一些跨域的问题,解决方案如下:

默认携带

ajax请求(不跨域)
jsonp请求

需要额外设置

cors(跨域资源贡献)请求(XMLHttpRequest):xhr.withCredentials = true;
fetch请求(fetch接口)credentials:“include”;//omit、same-origin
服务端也必须设置响应头请求(表示允许客户端的凭证,否则服务端取不到前台发送的cookie): Access-Control-Allow-Credentials:true

踩过的一些坑

cookie不区分端口号: 相同doamin不同端口下同一path的cookie有可能被覆盖
cookie 有作用域的概念:domain规定主域名、子域名之间cookie的分享,path规定不同目录下的cookie的分享,二者共同绝定了cookie的作用域.

总结

cookie的生命周期:

1、cookie的创建:服务端通过Set-Cookie的http头要求客户端创建,并给予其规定生命长度

2、cookie的使用:客户端每次请求都会根据path、domain通过Cookie的http头将cookie信息传送给服务端

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值