cookie 详解 与 封装 实用的cookie
在WEB前端开发中,cookie是必不可少的,网上也有很多开源的库可以使用,不过我还是想自己总结一下,做个笔记并封装一个实用的库。
(1)什么是cookie?
从web 角度 cookie是用于存储信息为下次访问 或者 与服务器之间传递信息的,
它可以记住用户上次操作了什么,操作到哪里了,为智能的操作提供基础。
它有自己的操作方式,有自己的大小,不过它的操作方式不太方便,可以依赖第三方库(下面我自己封装了一个)。
(2)cookie的基础知识点:
它有大小限制,一般不超过4kb,超出的将不再保存。
cookie 是不安全的,能通过查看cookies 或者 与服务器传递的header 中看到,所以不能报存重要的私密信息,如 用户的密码。
cookie 有自己的过期时间,可以用它来清除cookie。
cookie 保存的是字符串,多个cookies 之间用 ‘; ’分割,注意分号后还有一个空格,cookie 的key和value之间是“=”相连。
cookie 有其他高级存储方式如:path,domain,secure;
(3)cookie的简单操作:
1.存储和修改cookie:
document.cookie = 'key=value';
2.删除cookie:
document.cookie = 'key=value;expires=过去的时间.toUTCString()';
(4)cookie的高级操作:
1.过期时间(expires)
cookie 不是对象,不能通过操作对象的方式删除某个cookie,你可能会说把value设置为null或者undefined可以吗?答案是不可以,设置了null/undefined 获取的值
就是null/undefined,这条cookie是一直存在,并没有删除。如下图:
expires 的作用就在此刻显示了出来,通过设置过期时间可以删除这条cookie,同时也可以把过期时间延迟,从而延长这个cookie存在的时间,默认情况下,
expires 是 session,关闭浏览器cookie清除。
由于上面说过,cookie是String 类型的,那保存的时间格式也只能是字符串类型的,我们可以用toUTCString()把时间格式化成字符串,我们也可以
用toGMTString(),不过toGTMString()已经被toUTCString代替了(来自w3c),
2.路径(path)
path默认是当前浏览网页的父级文件夹,我们可以通过设置path 实现跨多个文件共用这条cookie。例如:
我有这个文件,截图如下:
我在setCookie.html中写下:
document.cookie='from=我是来自setCookie;path=/testCookie';
注意:我把path设置为‘/testCookie’,在getCookie.html中写下:
console.log('我是twoFile里面的getCookie,获取的cookie是:'+document.cookie);
设置的结果:
获取的结果:
从中可以看出我在one文件夹中设置的cookie,在two文件夹中获得了。
3.域(domain)
cookie 可以通过设置domain实现同域访问,前提是path='/',这里一定要注意是同域,而非跨域。
比如 http://news.baidu.com 与 https://www.baidu.com ,如果想设置同域访问,设置如下:
document.cookie = 'key=value;path=/;domain=baidu.com';
4.安全(secure)
我上面说了,cookie是不安全的,为何cookie有个安全(secure)呢?
其实大家不要误解了这个安全,如果设置了secure ,则保证 cookie 与服务器之间的数据传输过程加密,但是保存在本地的并没有发生任何改变,
有人说那我可以前端加密,算我没说,后面我们在聊聊前端加密问题,现在仅仅谈论secure的作用,我感觉这个作用不大,搞开发这么长时间了,直到现在没
有用过,(如有不同意见谢谢批评指出)。用法如下:
document.cookie = 'key=value;secure';
(5)问题:(cookie 与服务器传输,怎么传输的,在什么地方看到的,服务器(我用的node.js)如何获得?)
cookie与服务器传输是在Request Headers 中,如下图:
不过在header中分两种情况:
1.同域:服务器和web在统一域名下,这种情况下cookie默认是加到header中的,
2.跨域:服务器和web不在统一域名下,这种情况下就相对复杂了,但是这种情况在实际开发中是最常见的,
因为前后台分离是大势所趋,人心所向。那我们细细谈谈。其实,跨域下默认header 没有cookie的,原因很明显,那就是相对性的安全,这点也很好理解,
那问题是,我们如何解决让header中有cookie呢?
xhr.withCredentials = true;
加上这段就可以了,这就解决了跨域安全策略,告诉ajax 放心传cookie吧,这个API是可以信赖的,
注意:如果同域 这个参数是没有用的 无论true或者false(Setting withCredentials has no effect on same-site requests.)。
前端解决了,问题是,你给cookie,服务器想要么,如果不想要,ajax就会报错(我的片面理解)。服务器若想要cookie,拿node.js为例 设置如下:
app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Credentials", "true"); res.header("Access-Control-Allow-Origin", "http://localhost:63342"); });
特别注意: 给一个带有withCredentials的请求发送响应的时候,服务器端必须指定允许请求的域名,不能使用'*'.上面这个例子中,如果响应头是这样
的:Access-Control-Allow-Origin: * ,则响应会失败.在这个例子中 Access-Control-Allow-Origin 的值是 http://localhost:63342
这个指定的请求域名。
(6)个人认为开发中应用场景
登录记住两周功能:这个例子,记住的不是用户的帐号和密码,那是不安全的,而是后台根据用户信息、浏览器情况、ip等合成并返回一个用
户登录标识符(如 uid),记在cookie中,等下次进入或者刷新时,读取这个uid,判断是否已经登录了,并返回登录后应该返回的信息。
上面的是自己的拙见,若有错误,请无私的批评,谢谢大家!
好了cookie基本说完了,咱们实战一下,这是我封装的cookie用法:
1 (function ($window, $document) { 2 function isUndefined(value) { 3 return typeof value === 'undefined'; 4 } 5 6 function isDefined(value) { 7 return typeof value !== 'undefined'; 8 } 9 10 function isString(value) { 11 return typeof value === 'string'; 12 } 13 14 function getBaseHref() { 15 var oBase = $document.getElementsByTagName('base')[0]; 16 if (!oBase) { 17 return ''; 18 } 19 var href = oBase.getAttribute('href'); 20 return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; 21 } 22 23 function cookieWriter(key, value, options) { 24 var path, expires, defaultPath = getBaseHref(); 25 options = options || {}; 26 27 path = isDefined(options.path) ? options.path : defaultPath; 28 if (isUndefined(value)) { 29 expires = 'Thu, 01 Jan 1970 00:00:00 GMT'; 30 } 31 if (isString(expires)) { 32 expires = new Date(expires); 33 } 34 var str = encodeURIComponent(key) + '=' + encodeURIComponent(value); 35 str += expires ? ';expires=' + expires.toUTCString() : ''; 36 str += path ? ';path=' + path : ''; 37 str += options.domain ? ';domain=' + options.domain : ''; 38 str += options.secure ? ';secure' : ''; 39 $document.cookie = str; 40 } 41 42 function cookiesReader() { 43 var currentCookie = $document.cookie || '', 44 cookie, index, lastCookies = {}, name; 45 46 var cookieArray = currentCookie.split('; '); 47 48 for (var i = 0; i < cookieArray.length; i++) { 49 cookie = cookieArray[i]; 50 index = cookie.indexOf('='); 51 if (index > 0) { 52 name = decodeURIComponent(cookie.substring(0, index)); 53 lastCookies[name] = decodeURIComponent(cookie.substring(index + 1)); 54 } 55 } 56 return lastCookies; 57 } 58 59 function getCookieByKey(key) { 60 var lastCookies = cookiesReader(); 61 for (var i in lastCookies) { 62 if (i === key) { 63 return lastCookies[i]; 64 } 65 } 66 return ''; 67 } 68 69 function toJson(value) { 70 try { 71 return JSON.parse(value); 72 } catch (e) { 73 return value; 74 } 75 } 76 77 $window.$cookie = { 78 //获取cookie 79 get: function (key) { 80 return getCookieByKey(key); 81 }, 82 //获取cookie对象 83 getObject: function (key) { 84 return JSON.parse(getCookieByKey(key)); 85 }, 86 //获取全部cookies,allParse 是否完全解析josn 87 getAll: function (allParse) { 88 if (!allParse) { 89 return cookiesReader(); 90 } 91 var lastCookies = cookiesReader(); 92 93 for (var i in lastCookies) { 94 lastCookies[i] = toJson(lastCookies[i]); 95 } 96 return lastCookies; 97 }, 98 //设置或者修改cookie,value是字符串 99 put: function (key, value, options) { 100 cookieWriter(key, value, options); 101 }, 102 //设置或者修改cookie,value是对象 103 putObject: function (key, value, options) { 104 value = JSON.stringify(value); 105 cookieWriter(key, value, options); 106 }, 107 //移除cookie 108 remove: function (key) { 109 cookieWriter(key); 110 }, 111 //移除全部cookies 112 removeAll: function () { 113 var cookies = cookiesReader(); 114 var keys = Object.keys(cookies); 115 for (var i in keys) { 116 this.remove(i); 117 } 118 } 119 }; 120 })(window, document);
测试代码:
1 <button id="addBtn">添加</button> 2 <button id="removeBtn">移除</button> 3 <button id="getBtn">获取</button> 4 <script> 5 var addBtn= document.getElementById('addBtn'); 6 var getBtn=document.getElementById('getBtn'); 7 var removeBtn=document.getElementById('removeBtn'); 8 9 addBtn.onclick=function(){ 10 $cookie.put('str','zhang',{path:'/'}); 11 $cookie.putObject('obj',{name:'zhang'},{path:'/'}); 12 }; 13 14 getBtn.onclick=function(){ 15 console.log($cookie.getObject('str')); 16 console.log($cookie.getObject('obj')); 17 console.log($cookie.getAll(true)); 18 }; 19 20 removeBtn.onclick=function(){ 21 $cookie.remove('str'); 22 }; 23 </script>
上面的是我的总结,如果大家发现什么地方,希望批评指出,共同进步,谢谢大家。