关于cookie:cookie-时效无限延长方案

作者:京东科技 刘清洁 1、痛点(*)自动化测试有2种模式,接口自动化和UI自动化。而UI自动化常常会被登录节点梗塞,例如验证码、图形、滑块等,只管有些形式能够辨认图形和定位滑块地位,但成功率都不高,无奈真正意义上实现自动化执行;而http接口的自动化测试前置如果依赖cookie,也无奈实现自动化执行。 a、怎么样能力绕过登录,实现从前端到后端的自动化执行 b、面对简单的登录验证无奈间接主动获取到cookie,须要人工操作登录,而cookie又有时效,不能短暂应用 本计划将无效解决以上问题,在面对简单的登录验证及有cookie时效的模式下,能够将短暂时效的cookie改为短暂无效,真正意义上实现UI自动化和依赖cookie鉴权的接口自动化。 2、什么是cookiecookie称之为会话跟踪技术,是一个很小的文本文件,是浏览器贮存在用户的机器上的。Cookie是纯文本,没有可执行代码。贮存一些服务器须要的信息,每次申请站点,会发送相应的cookie,这些cookie能够用来分别用户身份信息等作用 3、过期工夫查看形式关上浏览器,并转到您心愿查看 cookie 的网站。 按 F12 键关上浏览器的开发者工具。 在开发者工具的“调试工具”选项卡中,单击“存储”按钮。 在左侧的“网站数据”列表中,单击“Cookies”。 在右侧的“值”列表中,查看每个 cookie 的“Expires”或“Max-Age”字段。这些字段显示 cookie 的过期工夫。 4、cookie机制客户端发送一个申请到服务器 --》 服务器发送一个HttpResponse响应到客户端,其中蕴含Set-Cookie的头部 --》 客户端保留cookie,之后向服务器发送申请时,HttpRequest申请中会蕴含一个Cookie的头部 --》服务器返回响应数据 时效限度:每个cookie都有时效,默认的有效期是,会话级别:就是当浏览器敞开,那么cookie立刻销毁,然而咱们也能够在存储的时候手动设置cookie的过期工夫 5、cookie时效有限缩短计划(*)5-1、前提 a. 登录节点有验证机制,例如短信验证码、图形辨认、滑块等校验; b. cookie有时效,超过时效则须要从新登录; c. 同一个账号不会在多个平台退出或登录 5-2、实现原理 此计划是通过一个微服务提供接口,供自动化调用,通过传递账号,返回永恒cookie,将此步嵌入到自动化流程中,代替登录并获取cookie的节点,并将cookie的时效永恒缩短,并不会时效,以保障后续自动化流程永恒循环失常执行。 5-3、外围流程步骤 步骤1:先手工登录,从header中获取cookie,将此cookie和时效值保留在微服务平台(一个账号只需一次手工登录,后续永恒不须要操作登录)。 步骤2:微服务平台将此账号、cookie、时效值、关联的业务接口进行长久化存储,并跟进时效值计算出轮询时长,并触发轮询工作执行,工作中将携带此cookie去调用业务接口,放弃长会话,并hold过程期待,在轮询时长达到时,继续执行工作执行,再次hold过程期待,继续循环,以保障次cookie的会话永恒放弃住。 步骤3:自动化工作执行前会调用微服务接口,通过账号获取到永恒cookie,携带此cookie执行后续自动化工作。 6、落地案例目前通过下方计划,已实现了cookie一次配置,短暂应用的目标。 实际成果比照 之前:ui自动化和http接口自动化执行时经常出现cookie过期,须要手工从新登录,并在自动化平台上更新cookie,比拟繁琐,且影响凌晨主动执行成功率 当初:应用下面计划后,只需手工在cookie微服务平台上配置一次cookie,当前不再须要更新cookie 7、专利形容https://zhuanli.tianyancha.com/811840799431036187d34680d5b10ae3

March 28, 2023 · 1 min · jiezi

关于cookie:如何获取b站cookie

第一步:关上BILIBILI弹幕视频网站,并且确保曾经登录了您的账户第二步:选中浏览器窗口的状况下,按下键盘上的F12按键进入测试界面,并选中“Network”抉择夹第三步:选中浏览器窗口的状况下,按下键盘上的“Ctrl + R”键,并将列表往上拖第四步:选中第一个“www.bilibili.com”选项,并抉择右侧“Headers”选项卡第五步:在选项卡中的“Request Headers”-“cookie”中找到咱们的cookiecookie:后的“buvid…….”即是咱们须要的cookie。

March 12, 2023 · 1 min · jiezi

关于cookie:如何理解CookieSessionToken

一、前情提要因为许多文章更多是这三者的总结和比拟,而本文次要是对Cookie、Session、Token的了解,因而并不波及到具体的优缺点、生命周期等细节的货色 二、Cookie1.Cookie的实质:过来咱们去奶茶店买奶茶的时候,他会给你一张纸卡,你每生产一次,这张纸卡就会记录一次你的生产记录 2.Cookie存在的问题 因为你每次都须要记录(比如说奶茶店会给你盖章示意喝奶茶一次),Cookie的长度通常来说比拟长(盖章太多),这样服务端和客户端之间传递的信息量就会比拟大Cookie不平安,因为在客户端进行存储,他人能够依据本地的Cookie来进行假装,从而对服务端的平安产生威逼因为在客户端进行存储,当在A电脑登录时,能传递信息给客户端,但当在B电脑登录时,却没有了。比方我想在任何设施查看购物车信息就没有方法通过Cookie进行存储三、Session1.session的实质:当咱们去奶茶店买奶茶的时候,他会给你一张卡,下面有卡号,咱们能够通过卡号,你每生产一次,让店员在操作机上给你记录一次2.解决下面Cookie的问题 因为SessionID(卡号)是一串数字,绝对于Cookie来说(盖章),它是没有那么长的,这样客户端和服务端之间传递的信息量就小假如应用Cookie实现Session时,因为客户端只存储了SessionID,那么即便SessionID被窃取,也不会对服务端的平安产生影响,只会对你的信息产生影响罢了(谁让你本人丢了呢?doge)四、Token1.为什么要引入Token? 仔细的同学可能发现了,Cookie存在的第三个问题呢,怎么Session没解决掉呢,而这就是咱们为什么要引入Token的起因之一服务器须要存储SessionID,这会加大服务端的压力,而Token不须要存储在服务端在分布式中,如果咱们没有存储SessionID的服务器B去申请服务器A,会呈现无奈申请的状况2.Token的验证过程(留神这里不是服务器端和token进行比拟,他是整个token中曾经含有了签名,让token本人含有的签名和破解密钥后的签名进行比拟)

December 25, 2022 · 1 min · jiezi

关于cookie:前端应该知道的Cookie知识

前言最近应用next.js来开发前端网站,在登录环节发现cookie的存储和跨域存在问题,始终没弄懂cookie的原理,看了网上好多大佬的文章,大有播种分享给大家。 Cookie介绍HTTP cookie(Web cookie,浏览器 cookie)是服务器发送到用户 Web 浏览器的一小段数据。浏览器可能会存储 cookie 并将其与稍后的申请一起发送回同一服务器。通常,HTTP cookie 用于判断两个申请是否来自同一个浏览器——例如,让用户放弃登录状态。它为无状态HTTP 协定 记住有状态信息。 Cookies次要用于三个目标: 1、会话治理:如登录、购物车、游戏分数或服务器应记住的任何其余内容2、个性化:如用户偏好、主题和其余设置3、追踪:如记录和剖析用户行为 1、创立 cookie接管到 HTTP 申请后,服务器能够发送一个或多个Set-Cookie响应头。浏览器通常存储 cookie 并将其与Cookie HTTP 标头内的同一服务器的申请一起发送。您能够指定不应发送 cookie 的过期日期或时间段。您还能够对特定域和门路设置附加限度,以限度 cookie 的发送地位。 Set-Cookie和Header Cookie HTTP 响应(Response)标头(Header)的Set-Cookie作用:从服务器发送cookie到用户代理。一个简略的 cookie 设置如下: Set-Cookie: <cookie-name>=<cookie-value>这批示服务器发送标头通知客户端存储一对cookie: HTTP/2.0 200 OKContent-Type: text/htmlSet-Cookie: yummy_cookie=chocoSet-Cookie: tasty_cookie=strawberry而后,对于服务器的每个后续申请,浏览器都会应用标头将所有先前存储的 cookie 带回服务器Cookie。 GET /sample_page.html HTTP/2.0Host: www.example.orgCookie: yummy_cookie=choco; tasty_cookie=strawberry2、Cookie 的生命周期 cookie 的生命周期能够通过两种形式定义: 1、以后会话完结时:会删除会话cookie。(浏览器定义“以后会话”何时完结,一些浏览器在重启时应用会话复原。这可能会导致会话 cookie 无限期地继续)2、永恒cookie:在Expires属性指定的日期或属性指定的一段时间后删除Max-Age。 例如: Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT;留神:1、当您设置Expires日期和工夫时,它们与设置 cookie 的客户端相干,而不是服务器。2、要删除Cookie,须要将Max-Age设置为0,并且将Cookie的值设置为null。不要将Max-Age指令值设置为-1正数。否则,浏览器会将其视为会话cookie。3、如果您的站点对用户进行身份验证,它应该从新生成并从新发送会话cookie,即便是曾经存在的,只有用户进行身份验证。这种办法有助于避免会话固定攻打,第三方能够重用用户的会话。 3、限度对 cookie 的拜访 ...

August 8, 2022 · 2 min · jiezi

关于cookie:cookie在前端页面的使用规范

cookie 是存储在浏览器中的字符串数据,它是 HTTP 协定的一部分。 cookie 通常是由 Web 服务器应用响应头字段 Set-Cookie 设置的。而后浏览器将符合要求的 cookie 数据主动增加到申请头字段 Cookie 中。 cookie 常见的应用场景就是身份验证: 登录后,服务器在响应中应用 Set-Cookie HTTP-header 来设置具备惟一“会话标识符(session identifier)“的 cookie 数据。下次当申请被发送到同一个域时,浏览器会应用 Cookie HTTP-header 通过网络发送 cookie 数据。所以服务器就会晓得用户的身份。除此之外,在浏览器中,还能够应用 document.cookie 读取或设置 cookie 数据。 读取 cookiedocument.cookie 返回蕴含页面中所有无效 cookie 的字符串(依据域、门路、过期工夫和平安设置),以分号宰割,如上面的例子所示: name1=value1;name2=value2;name3=value3所有名和值都是 URL 编码的,因而必须应用 decodeURIComponent() 解码。 辅助函数:class CookieUtil { static get(name) { let cookieName = `${encodeURIComponent(name)}=`, cookieStart = document.cookie.indexOf(cookieName), cookieValue = null if (cookieStart > -1) { let cookieEnd = document.cookie.indexOf(';', cookieStart) if (cookieEnd == -1) { cookieEnd = document.cookie.length } cookieValue = decodeURIComponent( document.cookie.substring(cookieStart + cookieName.length, cookieEnd) ) } return cookieValue }}设置 cookie通过 document.cookie 属性设置新的 cookie 字符串。这个字符串在被解析后会增加到原有的 cookie 中。设置 document.cookie 不会笼罩之前存在的任何 cookie ,除非设置了已有的 cookie 。设置 cookie 的格局如下: ...

May 26, 2022 · 2 min · jiezi

关于cookie:Session是什么它与Cookie有什么区别

你好,是我琉忆。 明天咱们讲一讲Session与Cookie的区别 1、Session对象上一节简略介绍了Cookie,接下来简略介绍Session。Session和Cookie都是会话治理技术的一种。可能你会奇怪记住用户的信息有Cookie就够了,为什么还须要Session?那么咱们带着这个疑难一起来看看Session,以及比照两者的区别。 2、什么是Session?Session的翻译有:一场; 一节; 一段时间; (法庭的)闭庭,闭庭期; (议会等的)会议,会期;学年; (酒吧中)演奏会(尤指演奏爱尔兰音乐)等等多种意思。个别咱们拿来指代“会议”或者“会期”的意思。然而理论咱们说的时候都对立用英文名称来称说这种技术,它和Cookie一样都算是计算机术语。 Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会失落,而是在整个用户会话中始终存在上来。当用户申请来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将主动创立一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜爱查看图形,就能够将该信息存储在Session对象中。 当用户登录或拜访一些初始页面时,服务器会为客户端调配一个 SessionID。SessionID 是一个加密的随机数字,在 Session 的生命周期中保留在客户端。它能够保留在用户机器的 Cookie 中,也能够通过 URL 在网络中进行传输。用户通过 SessionID 能够注册一些非凡的变量,称为会话变量,这些变量的数据保留在服务器端。在一次特定的网站连贯中,如果客户端能够通过 Cookie 或 URL 找到SessionID,那么服务器就能够依据客户端传来的 SessionID 拜访会话保留在服务器端的会话变量。Session 的生命周期只在一次特定的网站连贯中无效,当敞开浏览器后,Session 会主动生效,之前注册的会话变量也不能再应用。 3、为什么须要Session须要Session的次要起因是它存储更平安,个别用户的登录状态都是应用Session来存,这样在每个页面之间切换时,咱们都能够追踪到以后用户的信息,显示用户的登录状态。那么为什么Session存储更平安呢?起因是因为它的文件存储在服务器端,用户是没有权限操作服务器的,除了服务器管理员有权限操作外。这样就能够防止非法用户窃取Session中的数据,从而保障了数据的安全性。反而客户端的电脑有被黑客入侵窃取文件的危险,或者是别的用户应用该客户端电脑时,间接窃取Cookie文件的危险,导致数据泄露的问题。 【如果你还没有关注我的话,能够点点关注,下次更新精彩博文我告诉你。】4、Session应用在哪些场合?因为Session数据是存储在服务器端的,安全性比Cookie要高。那么数据安全性要求比拟高,比拟私密的状况下都能够应用Session。 那么个别咱们会用Session存储用户的状态,不便在页面之间切换时仍旧显示登录状态。还能够作为缓存,缓存用户购物车数据。为什么购物车的数据不实用Cookie呢?起因很简略,如果用Cookie实现购物车的存储性能,当用户在A电脑放了3件商品到购物车中,用户在A电脑看购物车时3件商品都是能够看到的。然而当用户在B电脑登录账号查看购物车时,会发现购物车中一件商品都没有。如果应用Session就不存在这种问题。那么为什么会呈现这种状况呢?起因就在于存储数据的形式不同!首先Cookie是存储数据在客户端,Session是存储数据在服务端。那么当用户在A电脑存储数据到购物车时,如果存到Cookie中,就相当于把数据存储到了A电脑中,在B电脑天然读取不到该Cookie的数据。反而Session存储商品在服务器时,无论你换哪台电脑,都是能够间接从服务器获取该用户的信息展现的。 所以综合下来,总结就是Cookie存储数据在本地,安全性要求不高、不要求数据共享都能够应用它;Session存储数据在服务器,数据安全性要求高、须要共享数据,则能够抉择Session。 5、Cookie和Seesion有什么区别?简略介绍完Cookie和Session之后,我置信你肯定有很多疑难,Cookie和Session到底有什么区别?咱们简略从多个角度来进行比照。比照后果如下:那么比照下来,最要害的是,如果存储的数据安全性要求比拟高,比拟私密,那么数据就存储在Session中,如果安全性要求不那么高就存储在Cookie中。起因是Cookie存储在本地,黑客能够在通信过程中窃取Cookie解密查看存储信息。如果信息存储在Session中,Session的数据是缓存在服务器端的,黑客是没有权限操作服务器,对Session文件进行破解的,只能获取到SessionID。而SessionID是服务端程序获取Session数据的惟一标识。 6、我写的书开始预售了!最近正在写一本《ASP.NET Web动静网站》开发的书,预计2月底写完,敬请期待~预售网址:【村长编写】14天零根底到入门搞定ASP.NET Web网页开发【书籍】预售更多编程常识获取,能够关注公众号:琉忆编程库。

February 19, 2022 · 1 min · jiezi

关于cookie:Web网站开发中Cookie是什么

你好,是我琉忆。明天咱们讲一讲什么是Cookie,怎么了解Cookie。 在咱们Web开发中,例如要想短暂的存储一个用户的信息,到底须要应用什么样的一个形式进行贮存?咱们一起来看看。 1、Cookie对象咱们先从Cookie开始介绍,在ASP.NET开发中,提供了Cookie对象。该对象曾经封装好了所有对Cookie相干的操作,底层的封装实现咱们不须要关怀,须要重点把握该对象的操作和应用。 2、什么是Cookie?Cookie的翻译解释有以下几种:曲奇; 精明强干的人; 刚强的人; 网络饼干(网络或互联网使用者发给地方服务器信息的计算机文件)。很显著对该英文的最好解释是“网络饼干”。它是一个保留在客户机中的简略的文本文件,是某些网站为了分别用户身份,进行Session跟踪而贮存在用户本地终端上的数据(通常通过加密),由用户客户端计算机临时或永恒保留的信息。 因为Cookie具备能够保留在客户机上的神奇个性, 因而它能够帮忙咱们实现记录用户个人信息的性能, 而这所有都不用应用简单的CGI等程序实现。举例来说, 一个 Web 站点可能会为每一个访问者产生一个惟一的ID, 而后以 Cookie 文件的模式保留在每个用户的机器上。如果应用浏览器拜访 Web, 会看到所有保留在硬盘上的 Cookie。在这个文件夹里每一个文件都是一个由“名/值”对组成的文本文件,另外还有一个文件保留有所有对应的 Web 站点的信息。在这里的每个 Cookie 文件都是一个简略而又一般的文本文件。透过文件名, 就能够看到是哪个 Web 站点在机器上搁置了Cookie,当然站点信息在文件里也有保留。 Cookie次要由以下内容组成: Cookie是一段不超过4KB的小型文本数据,由一个名称(Name)、一个值(Value)和其它几个用于管制Cookie有效期、安全性、应用范畴的可选属性组成。其中: (1)Name/Value:设置Cookie的名称及绝对应的值,对于认证Cookie,Value值包含Web服务器所提供的拜访令牌。 (2)Expires属性:设置Cookie的生存期。有两种存储类型的Cookie:会话性与持久性。Expires属性缺省时,为会话性Cookie,仅保留在客户端内存中,并在用户敞开浏览器时生效;持久性Cookie会保留在用户的硬盘中,直至生存期到或用户间接在网页中单击“登记”等按钮完结会话时才会生效。 (3)Path属性:定义了Web站点上能够拜访该Cookie的目录。 (4)Domain属性:指定了能够拜访该 Cookie 的 Web 站点或域。Cookie 机制并未遵循严格的同源策略,容许一个子域能够设置或获取其父域的 Cookie。当须要实现单点登录计划时,Cookie 的上述个性十分有用,然而也减少了 Cookie受攻打的危险,比方攻击者能够借此动员会话定置攻打。因此,浏览器禁止在 Domain 属性中设置.org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻打产生的范畴。 (5)Secure属性:指定是否应用HTTPS平安协定发送Cookie。应用HTTPS平安协定,能够爱护Cookie在浏览器和Web服务器间的传输过程中不被窃取和篡改。该办法也可用于Web站点的身份甄别,即在HTTPS的连贯建设阶段,浏览器会查看Web网站的SSL证书的有效性。然而基于兼容性的起因(比方有些网站应用自签订的证书)在检测到SSL证书有效时,浏览器并不会立刻终止用户的连贯申请,而是显示平安危险信息,用户仍能够抉择持续拜访该站点。因为许多用户不足安全意识,因此仍可能连贯到Pharming攻打所伪造的网站。 (6)HTTPOnly 属性 :用于避免客户端脚本通过document.cookie属性拜访Cookie,有助于爱护Cookie不被跨站脚本攻打窃取或篡改。然而,HTTPOnly的利用仍存在局限性,一些浏览器能够阻止客户端脚本对Cookie的读操作,但容许写操作;此外大多数浏览器仍容许通过XMLHTTP对象读取HTTP响应中的Set-Cookie头。 须要晓得的是:一个网站反对多个Cookie的应用,每个Cookie的键名能够不同,每个键名能够存储的货色都能够不一样。如果键名一样,那么后一个键名的值会笼罩前一个键名的值。Cookie 技术有很多局限性,例如: 1)多人共用一台计算机,Cookie 数据容易泄露。 2)一个站点存储的 Cookie 信息无限。 3)有些浏览器不反对 Cookie。 4)用户能够通过设置浏览器选项来禁用 Cookie。 正是因为以上 Cookie 的一些局限性,所以,在进行会话治理时,SessionID 通常会抉择Cookie 和 URL 两种形式来保留,而不是只保留在 Cookie 中。 【如果你还没有关注我,能够点点关注,下次更新精彩博文,我告诉你】 3、为什么须要Cookie?简略介绍了Cookie是什么、组成和应用过程后,咱们来看看为什么须要用到Cookie。 ...

February 18, 2022 · 1 min · jiezi

关于cookie:java学习中cookie原理

1.cookie原理1)总的来看Cookie像是服务器发给浏览器的一张“会员卡”,浏览器每次向服务器发 送申请时都会带着这张“会员卡”,当服务器看到这张“会员卡”时就能够辨认浏览器的身份。实际上这个所谓的“会员卡”就是服务器发送的一个响应头: 2)如图Set-Cookie这个响应头就是服务器在向服务器发“会员卡”,这个响应头的名字是Set-Cookie,后边JSESSIONID=95A92EC1D7CCB4ADFC24584CB316382E和 Path=/Test_cookie,是两组键值对的构造就是服务器为这个“会员卡”设置的信息。java培训浏览器收到该信息后就会将它保留到内存或硬盘中。3)当浏览器再次向服务器发送申请时就会携带这个Cookie信息: 这是浏览器发送的申请报文,两头画红框的就是Cookie信息,这里能够了解为浏览器这次带着“会员卡”再次拜访服务器。于是服务器就能够依据Cookie信息来判断浏览器的状态。原理图如下:

January 6, 2022 · 1 min · jiezi

关于cookie:Cookie的Secure属性

基于平安的思考,须要给cookie加上Secure和HttpOnly属性,HttpOnly比拟好了解,设置HttpOnly=true的cookie不能被js获取到,无奈用document.cookie打出cookie的内容。 Secure属性是说如果一个cookie被设置了Secure=true,那么这个cookie只能用https协定发送给服务器,用http协定是不发送的。换句话说,cookie是在https的状况下创立的,而且他的Secure=true,那么之后你始终用https拜访其余的页面(比方登录之后点击其余子页面),cookie会被发送到服务器,你无需从新登录就能够跳转到其余页面。然而如果这是你把url改成http协定拜访其余页面,你就须要从新登录了,因为这个cookie不能在http协定中发送。 例子是: 前提条件:https://localhost:9102利用对cookie设置了Secure=true 拜访 https://localhost:9102/manager输出用户名、明码,用IE或者Chrome的developer tool会看到response的header里,set-cookie的值里有Secure属性登录后,持续拜访https://localhost:9102/manage...,能够失常看到内容批改url,拜访http://localhost:9100/manager...,会跳转到登录页面,因为cookie在http协定下不发送给服务器,服务器要求用户从新登录起因剖析: 服务器开启了Https时,cookie的Secure属性应设为true; 解决办法: 1.服务器配置Https SSL形式,参考:https://support.microsoft.com... 2.批改web.config,增加: <system.web> <httpCookies httpOnlyCookies="true" requireSSL="true" /><system.web>

December 2, 2021 · 1 min · jiezi

关于cookie:数千用户将包含敏感数据的-Firefox-cookie-数据库提交至-GitHub

据国外媒体报道,伦敦铁路旅行服务公司 Trainline 的平安工程师 Aidan Marlin 发现蕴含敏感数据的数千个Firefox cookie数据库呈现在 GitHub 的存储库中,这些数据可能被用于劫持曾经过身份验证的会话。 这些 cookie.sqlite 数据库通常位于 Firefox 配置文件文件夹中,用于在浏览会话之间存储 cookie。当初能够通过应用特定的查问参数在 GitHub 上搜寻找到,这就是所谓的 “Github search dork”。 目前受影响的 GitHub 用户大多工作在跨多台计算机的公共环境,当他们从 Linux 主目录提交代码,并将其推送到公共存储库时,Sqlite 数据库就会被蕴含在内。 Marlin 坦言,用户在提交代码并将其推送到公共存储库时,并未被动阻止他们的 cookies.sqlite 数据库被蕴含在内,所以这个 cookie 泄露问题用户也占肯定责任。 “但目前这个 GitHub dork 的点击量靠近 4500 次,所以我认为 GitHub 也有任务器重此事件并将其修复。” 然而,Marlin 却被GitHub 代表告知“用户泄露的证书不在 Bug Bounty 打算的范畴内”,这意味着Github 近期未打算公布补丁修复此问题。  Marlin 认为 GitHub 没有认真对待用户的平安和隐衷,并称 GitHub 至多能够阻止这个GitHub dork 失去搜寻后果。

November 23, 2021 · 1 min · jiezi

关于cookie:js清除全部cookie

试了很多网上写的革除cookie的代码,逻辑是将cookie有效期设为过期工夫,然而没有成果,最初发现还要再加个max-age=0 const clearCookie = () => { var keys = document.cookie.match(/[^ =;]+(?==)/g); if (keys) { for (var i = keys.length; i--; ) { document.cookie = keys[i] + "=0;expires=" + new Date(0).toUTCString() + ";max-age=0"; } }};

September 10, 2021 · 1 min · jiezi

关于cookie:cookie的sameSite

概念SameSite 阻止浏览器将 cookie 与跨站点申请一起发送。次要指标是升高跨起源信息泄露的危险。它还提供了一些针对跨站点申请伪造攻打的爱护。该标记的可能值为 Lax 或 Strict。 SameSite能够有上面三种值:Strict仅容许一方申请携带Cookie,即浏览器将只发送雷同站点申请的Cookie,即以后网页URL与申请指标URL完全一致。Lax容许局部第三方申请携带CookieNone无论是否跨站都会发送Cookie 以前浏览器默认值为None当初为Lax,所以当初的跨站ajax申请默认不会再携带cookie。 对于ajax(XMLHttpRequest)跨域申请携带cookie的一些了解1、ajax跨域申请默认不携带cookie,必须设置XMLHttpRequest的withCredentials为ture2、如果这个ajax申请是跨站申请,即便设置了withCredentials也不会携带cookie,必须强行把SameSite设置成None才会携带cookie。不过须要留神:SameSite设置成None后,Cookie就必须同时加上Secure属性(Secure属性是说如果一个cookie被设置了Secure=true,那么这个cookie只能用https协定发送给服务器,用http协定是不发送的)

April 24, 2021 · 1 min · jiezi

关于google:欲替代第三方-Cookie谷歌正式推行-FLoC惨遭各方抵制

第三方 Cookie 技术能够让浏览器标记出较为清晰的用户画像,为网络商业化广告投放发明了更好的条件。谷歌作为世界上最大的公司之一,Cookie 技术与其以广告收益为主的商业模式密切相关。 但面对近几年用户隐衷保护意识的崛起、政策束缚的趋严、广告商业模式的变迁,2020 年 1 月,谷歌发表打算在两年内进行在其 Chrome 浏览器中应用第三方 cookie。本月初,谷歌进一步示意,明年起 Chrome 浏览器将逐渐淘汰第三方 Cookie,并且,在 Cookie 隐没后,不会建设代替标识符来跟踪集体在网络上浏览的状况。 此前,谷歌也曾退出 FLoC(Federated Learning of Cohorts)技术作为“代替” Cookie 的计划。与 Cookies 定义、追踪集体网络流动不同,FLoC 将用户分成不同群组,依据群组类别投放广告。谷歌官网示意,FLoC 比第三方 cookies 更可能爱护用户隐衷。 FLoC 曾经在本月开始测试,并在 Chrome 浏览器上默认开始。但此举已受到业界各方的抵制。除了电子前沿基金会(EFF)的痛批、DuckDuckGo 推出了默认阻止 FLoC 的浏览器扩大程序,就连同样应用 Chromium 内核的 Brave、Vivaldi、Microsoft Edge 等浏览器开发商也都不愿为它提供反对。 DuckDuckGo 指出,FLoC 对隐衷无害,因为它将用户依照网上行为记录被分到某个群组中,任何网站都能够获得该 FLoC ID 来瞄准用户并收集用户浏览器指纹,包含浏览器类型、版本、操作系统、屏幕大小、时区、是否执行 JavaScript 等。 WordPress 明天也发布公告示意,认为谷歌的新 FLoC 追踪技术存在安全隐患,并打算在 WordPress 网站上默认进行屏蔽。 FloC 是什么?FLoC 全称叫做广告追踪技术群组联结学习,利用机器学习剖析 Chrome 浏览器的网络行为,将有雷同兴趣爱好的用户进行归类,而后向其推送相干的广告内容。 FLoC 背地的核心思想是,浏览器将用户拜访的网站数据输出一个机器学习算法,该算法在浏览器中运行。该算法确定该用户属于哪个群组,将该用户与大量具备类似趣味的其余用户群体进行匹配。例如,浏览器可能会看到一个特定的用户拜访了很多对于足球、时尚和烘焙的网站,该用户可能会被放入其余足球、时尚和烘焙爱好者的群组中。广告主能够依据这些群体内用户的趣味定向这些群体,实现基于趣味的指标定向。 但个人用户的浏览数据不会来到他们的浏览器。所以在下面的例子中,浏览器不会申明用户拜访了哪个足球、时尚和烘焙网站。它只会收回一个「队列 ID 」,申明用户属于哪个队列。谷歌示意,如果这些群组足够大,就不可能追踪个人用户,这意味着隐衷将失去爱护。 尽管如此,业界也有专家指出这背地其实有着更为严重的安全隐患。身份辨认专家 ID5 的 CEO Mathieu Roche 认为,将用户分组可能会让个人用户更难理解他们的数据是如何被应用的,以及谁在针对他们。 ...

April 19, 2021 · 1 min · jiezi

关于cookie:response中的setcookie和request中的cookie

只有客户端能力设置Cookie,服务端若想让客户端减少一个Cookie项,须要在应答时,在Http头部中,通过应用Set-Cookie,将要设置的Cookie项发送给客户端。这样客户端,在下次访问时,会带上该Cookie项。依据Netscape cookie草案的形容,Cookie 是Web 服务器向用户的浏览器发送的一段ASCII码文本。一旦收到Cookie,浏览器会把Cookie的信息片断以"名/值"对(name-value pairs)的模式贮存保留在本地。这当前,每当向同一个Web 服务器申请一个新的文档时,Web 浏览器都会发送之站点以前存储在本地的Cookie。创立Cookie的最后目标是想让Web服务器可能通过多个HTTP申请追踪客户。有些简单的网络应用须要在不同的网页之间保持一致,它们须要这种会话状态的放弃能力。浏览器与Web服务器通过HTTP协定进行通信,而Cookie就是保留在HTTP协定的申请或者应答头部(在HTTP协定中,数据包含两局部,一部分是头部,由一些名值对形成,用来形容要被传输数据的一些信息。一部分是主体(body),是真正的数据(如HTML页面等))进行传送的。在HTML文档被发送之前,Web服务器通过传送HTTP 包头中的Set-Cookie 音讯把一个cookie 发送到用户的浏览器中。 上面是一个遵循Netscape cookie草案的残缺的Set-Cookie 头:Set-Cookie:customer=huangxp; path=/foo; domain=.ibm.com; expires= Wednesday, 19-OCT-05 23:12:40 GMT; [secure]Set-Cookie的每个属性解释如下: Customer=huangxp 一个"名称=值"对,把名称customer设置为值"huangxp",这个属性在Cookie中必须有。path=/foo 管制哪些拜访可能触发cookie 的发送。如果没有指定path,cookie 会在所有对此站点的HTTP 传送时发送。如果path=/directory,只有拜访/directory 上面的网页时,cookie才被发送。在这个例子中,用户在拜访目录/foo下的内容时,浏览器将发送此cookie。如果指定了path,然而path与以后拜访的url不符,则此cookie将被疏忽。domain=.ibm.com 指定cookie被发送到哪台计算机上。失常状况下,cookie只被送回最后向用户发送cookie 的计算机。在这个例子中,cookie 会被发送到任何在.ibm.com域中的主机。如果domain 被设为空,domain 就被设置为和提供cookie 的Web 服务器雷同。如果domain不为空,并且它的值又和提供cookie的Web服务器域名不符,这个Cookie将被疏忽。expires= Wednesday, 19-OCT-05 23:12:40 GMT 指定cookie 生效的工夫。如果没有指定生效工夫,这个cookie 就不会被写入计算机的硬盘上,并且只继续到这次会话完结。secure 如果secure 这个词被作为Set-Cookie 头的一部分,那么cookie 只能通过平安通道传输(目前即SSL通道)。否则,浏览器将疏忽此Cookie。一旦浏览器接管了cookie,这个cookie和对远端Web服务器的间断申请将一起被浏览器发送。例如 前一个cookie 被存入浏览器并且浏览器试图申请 URL http://www.ibm.com/foo/index.... 时,上面的HTTP 包头就被发送到远端的Web服务器。GET /foo/index.html HTTP/1.0 Cookie:customer=huangxp

April 10, 2021 · 1 min · jiezi

关于cookie:一文搞懂CookieStorageIndexedDB

关注公众号“执鸢者”,回复“材料”获取500G材料(各“兵种”均有),还有业余交换群等你一起来洒脱。(哈哈)随着前端技术的倒退,存储变的越来越重要,就目前来看,浏览器次要反对三类存储:Cookie、Storage、IndexedDB,上面别离介绍这三类存储形式。 一、Cookie1.1 定义Cookie是一个保留在浏览器中的简略的文本文件,该文件与特定的Web文档关联在一起,保留了该浏览器拜访这个Web文档时的信息,当浏览器再次拜访这个Web文档时这些信息可供该文档应用。(HTTP是无状态的协定,即HTTP协定自身不对申请和响应之间的通信状态进行保留,为了实现冀望的保留状态性能,引入了cookie技术)1.2 Cookie组成在理解Cookie组成之前先理解一下Cookie的整个申请流程,这个流程分为类:一类是没有Cookie信息状态下的申请,另一类是存有Cookie状态下的申请。通过下面的流程图能够看出,Cookie是在服务端生成的,通过查问材料理解到其是在从服务端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,响应报文中有该首部字段则告诉客户端保留Cookie,则Cookie的组成则跟Set-Cookie能够设置哪些值相干,目前次要有以下几类: NAME=VALUECookie的名称和值,其中NAME是惟一标识cookie的名称,不辨别大小写;VALUE是存储在Cookie里的字符串值,该值必须通过URL编码。 Domain=域名Cookie无效的域,发送到这个域的所有申请都会蕴含对应的Cookie。(若不指定则默认为创立Cookie的服务器的域名) Path=PATH申请URL中蕴含这个门路才会把Cookie发送到服务器(若不指定则默认为文档所在的文件目录) Expires=DATECookie的有效期,默认状况下,浏览器会话完结后会删除所有cookie。 Secure设置后仅在HTTPS平安通信时才会发送Cookie HttpOnly设置后只能在服务器上读取,不能再通过JavaScript读取Cookie const express = require('express');const app = express();app.get('/', (req, res) => { res.cookie('myCookie', 'myCookie', { expires: new Date(Date.now() + 900000), secure: true, httpOnly: true }); res.send('get申请曾经被解决');})app.listen(8090, () => { console.log('8090端口曾经启动!!!');});通过申请 http://127/.0.0.1:8090 来看看其后果:第一次返回的Cookie后果 后续申请所带的Cookie信息 1.3 Cookie特点每个Cookie不超过4096字节;每个域中Cookie个数有限度,就拿最新版来说:IE和Edge不超过50个;Firefox不超过150个;Opera不超过180个;Safari和Chrome没有限度;Cookie超过单个域的下限,浏览器会删除之前设置的Cookie;创立的Cookie超过最大限度,该Cookie会被静默删除;可设置生效工夫,没有设置则会话完结会删除Cookie;每个申请均会携带Cookie,若Cookie过去会带来性能问题;受同源策略限度1.4 Cookie的操作Cookie存储到浏览器端之后依然能够对其进行读、写、删除,因为js对Cookie操作的反对并不是很敌对,所以须要进行一些简略的封装。class CookieUtil { // 获取Cookie中的对应属性 static get(name) { const cookies = document.cookie; const cookiesArr = cookies.split(';'); for (let index = 0; index < cookiesArr.length; index++) { const presentCookieArr = cookiesArr[index].split('='); if (presentCookieArr[0] === name) { return presentCookieArr[1]; } } return null; } // 设置对应的Cookie值 static set(name, value, expires, path, domain, secure) { let cookieText = `${name}=${value}`; if (expires instanceof Date) { cookieText += `; expire=${expires.toGMTString()}`; } if (path) { cookieText += `; path=${path}`; } if (domain) { cookieText += `; domain=${domain}`; } if (secure) { cookieText += `; secure`; } document.cookie = cookieText; } // 删除对应的Cookie static deleteCookie(name) { CookieUtil.set(name, '', new Date(0)); }}二、Web StorageWeb Storage的目标是解决通过客户端存储不须要频繁发送回服务器的数据时应用cookie的问题,其提供了cookie之外的存储会话数据的路径和跨会话长久化存储大量数据的机制,其次要有两个对象:localStorage和sessionStorage,localStorage是永恒存储机制,sessionStorage是跨会话的存储机制。2.1 sessionStoragesessionStorage是跨会话的存储机制,具备以下特点:sessionStorage对象值存储会话数据,其生命周期会存储到浏览器敞开。(在该过程中刷新页面其数据不受影响)浏览器在实现存储写入时应用同步阻塞形式,数据会被立刻提交到存储。独立关上同一个窗口同一个页面或一个Tab,sessionStorage也是不一样的。存储空间大小限度为每个源不超过5M。// 应用办法存储数据sessionStorage.setItem('sessionName1', 'value1');// 应用属性存储数据sessionStorage.sessionName2 = 'value2';// 应用办法获得数据const sessionValue1 = sessionStorage.getItem('sessionName1');console.log('sessionValue1的值为:', sessionValue1);// 应用属性获得数据const sessionValue2 = sessionStorage.sessionName2;console.log('sessionValue2的值为:', sessionValue2);// 循环遍历sessionStaragefor (let index = 0; index < sessionStorage.length; index++) { // 应用key()办法取得指定索引处的名称 const key = sessionStorage.key(index); const value = sessionStorage.getItem(key); console.log('循环遍历后果:', key, value);}// 应用办法删除值sessionStorage.removeItem('sessionName1');// 应用delete删除值delete sessionStorage.sessionName2;// 应用clear()办法清空sessionStoragesessionStorage.clear();2.2 localStoragelocalStorage是永恒存储机制,具备以下特点:生命周期是永恒的,除非被革除,否则永恒保留。存储空间大小限度为每个源不超过5M。受同源策略限度。浏览器存储时采纳同步存储形式。// 应用办法存储数据localStorage.setItem('localName1', 'value1');// 应用属性存储数据localStorage.localName2 = 'value2';// 应用办法获得数据const localValue1 = localStorage.getItem('localName1');console.log('localValue1的值为:', localValue1);// 应用属性获得数据const localValue2 = localStorage.localName2;console.log('localValue2的值为:', localValue2);// 循环遍历localStaragefor (let index = 0; index < localStorage.length; index++) { // 应用key()办法取得指定索引处的名称 const key = localStorage.key(index); const value = localStorage.getItem(key); console.log('循环遍历后果:', key, value);}// 应用办法删除值localStorage.removeItem('localName1');// 应用delete删除值delete localStorage.localName2;// 应用clear()办法清空localStoragelocalStorage.clear();三、IndexedDB3.1 IndexedDB整个构造对于整个IndexedDB为上述图中所示: ...

February 28, 2021 · 3 min · jiezi

关于cookie:老生常谈Cookie与Session

Session简介Session是对于服务端来说的,客户端是没有Session一说的。Session是服务器在和客户端建设连贯时增加客户端连贯标记,最终会在服务器软件(Apache、Tomcat、JBoss)转化为一个长期Cookie发送给给客户端,当客户端第一申请时服务器会查看是否携带了这个Session(长期Cookie),如果没有则会增加Session,如果有就拿出这个Session来做相干操作 在这里援用他人家的一个小故事来加深印象:咱们晓得,咱们用浏览器关上一个网页,用到的是HTTP协定,理解计算机的应该都晓得这个协定,它是无状态的,什么是无状态呢?就是说这一次申请和上一次申请是没有任何关系的,互不意识的,没有关联的。然而这种无状态的的益处是疾速。所以就会带来一个问题就是,我心愿几个申请的页面要有关联,比方:我在www.a.com/login.php外面登陆了,我在www.a.com/index.php也心愿是登陆状态,然而,这是2个不同的页面,也就是2个不同的HTTP申请,这2个HTTP申请是无状态的,也就是无关联的,所以无奈单纯的在index.php中读取到它在login.php中曾经登陆了! 那咋搞呢?我不可能这2个页面我都去登陆一遍吧。或者用笨办法这2个页面都去查询数据库,如果有登陆状态,就判断是登陆的了。这种查询数据库的计划尽管可行,然而每次都要去查询数据库不是个事,会造成数据库的压力。 所以正是这种诉求,这个时候,一个新的客户端存储数据形式呈现了:cookie。cookie是把大量的信息存储在用户本人的电脑上,它在一个域名下是一个全局的,只有设置它的存储门路在域名www.a.com下 ,那么当用户用浏览器拜访时,php就能够从这个域名的任意页面读取cookie中的信息。所以就很好的解决了我在www.a.com/login.php页面登陆了,我也能够在www.a.com/index.php获取到这个登陆信息了。同时又不必重复去查询数据库。 尽管这种计划很不错,也很疾速不便,然而因为cookie 是存在用户端,而且它自身存储的尺寸大小也无限,最要害是用户能够是可见的,并能够随便的批改,很不平安。那如何又要平安,又能够不便的全局读取信息呢?于是,这个时候,一种新的存储会话机制:session 诞生了。 所以Session就是在一次会话中解决2次HTTP的申请的关联,让它们产生分割,让2两个页面都能读取到找个这个全局的session信息。session信息存在于服务器端,所以也就很好的解决了平安问题。 Cookie简介 Cookie在计算机中是个存储在浏览器目录中的文本文件,当浏览器运行时,存储在RAM中发挥作用(此种Cookies称作Session Cookies), 一旦用户从该网站或服务器退出,Cookie可存储在用户本地的硬盘上(此种Cookies称作Persistent Cookies) Cookie应用限度: Cookie必须在HTML文件的内容输入之前设置; 不同的浏览器对Cookie的解决不统一, 应用时肯定要思考; 客户端用户如果设置禁止Cookie, 则Cookie不能建设.并且在客户端,一个浏览器能创立的Cookie数量最多为300个,并且每个不能超过4KB, 每个Web站点能设置的Cookie总数不能超过20个 咱们从一个request申请中来看看cookie和session 客户端第一次发送一个http申请到服务器端时。request会解析申请中携带的jssesionid,用它去找到存在于利用中的session,因为此时服务端没有生成过jssesionid,那么就会调用session的创立办法,生成一个新的jssessionid服务器端承受客户端申请后,发送一个http响应到客户端,这个响应头中蕴含Set-Cookie头部,在该头部返回jssesionid的信息。当客户端再次发送该http申请时,就会在cookie信息中携带该jessionid这是一次http申请中(http://localhost:8080/test1),蕴含的申请和响应信息,是对一个零碎的首次拜访。申请头中,蕴含的Cookie信息,并没有上文提到的jsessionid, 那是因为这是对系统的首次拜访,零碎还没生成session。然而拜访之后,零碎就会生成一个session,而且,会在响应流中设置响应头Set-Cookie,其值为JESSIONID=xxx。这样浏览器对localhost:8080和cookie的分割就有了记忆 这是第二次申请http://localhost:8080/test1, 浏览器会被动在申请头增加包含jsessionid的cookie信息 强调一下cookie中的两个重要属性: domain示意的是cookie所在的域,默认为申请的地址,如网址为www.test.com/test/test.aspx,那么domain默认为www.test.com。而跨域拜访,如域A为t1.test.com,域B为t2.test.com,那么在域A生产一个令域A和域B都能拜访的cookie就要将该cookie的domain设置为.test.com;如果要在域A生产一个令域A不能拜访而域B能拜访的cookie就要将该cookie的domain设置为t2.test.com。path示意cookie所在的目录,默认为/,就是根目录。在同一个服务器上有目录如下:/test/,/test/cd/,/test/dd/,现设一个cookie1的path为/test/,cookie2的path为/test/cd/,那么test下的所有页面都能够拜访到cookie1,而/test/和/test/dd/的子页面不能拜访cookie2。这是因为cookie能让其path门路下的页面拜访。最初一个小总结1、cookie数据寄存在客户的浏览器上,session数据放在服务器上。2、cookie不是很平安,他人能够剖析寄存在本地的cookie并进行cookie坑骗,思考到平安该当应用session。3、session会在肯定工夫内保留在服务器上。当拜访增多,会比拟占用你服务器的性能,思考到加重服务器性能方面,该当应用cookie。4、单个cookie保留的数据不能超过4K,很多浏览器都限度一个站点最多保留20个cookie。

January 28, 2021 · 1 min · jiezi

关于cookie:软件测试cookie学习

一、什么是cookie“Cookie”是小量信息,由网络服务器发送进去以存储在网络浏览器上,从而下次这位举世无双的访客又回到该网络服务器时,可从该浏览器读回此信息。这是很有用的,让浏览器记住这位访客的特定信息,如上次访问的地位、破费的工夫或用户首选项(如样式表)。 Cookie 是个存储在浏览器目录的文本文件,当浏览器运行时,存储在 RAM 中。一旦你从该网站或网络服务器退出,Cookie 也可存储在计算机的硬驱上。当访客完结其浏览器对话时,即终止的所有 Cookie。 Cookie是指网站用于分别身份,进行会话(session)跟踪而存储在客户端的数据。它是有服务器产生并发送给客户端的。其用处是提供一个不便的性能以简化用户输出,节俭拜访页面的工夫。 Cookie能够由下列对象创立 Javascript、VBScript等HTML页面中的客户端脚本 应用MS win32 Internet函数(Internetsetcookie和Internetgetcookie)的win32程序 JSP/ASP等页面中的服务器端脚本。 二、禁用cookie可能会导致某些web零碎无奈失常运行 使用户无奈进行匿名拜访 使web零碎无奈跟踪用户的浏览习惯。 三、第一方跟第三方cookie第一方cookie是与宿主域名相关联的cookie 第三方cookie是来自任何其余域名的cookie 四、长久cookie和会话cookieCookie既能够存储在内存中(会话cookie),也能够存粗在硬盘中(长久cookie)长久cookie会被写入用户配置文件夹下的cookie文件夹,浏览器临时文件索引会应用指向长久cookie文件的指针进行更新。 五、cookie测试对于会话cookie,要测试其在不退出web零碎的状况下起作用,同时也要测试退出web零碎后不起作用,即从新登录时没有上次操作的痕迹。 对于长久cookie,要测试其在退出web零碎后依然起作用,即从新登录时保留上次操作的痕迹。 对于长久cookie,还要进行cookie的更新测试,即更新页面信息或者进行其余操作后,再次登录,查看cookie是否更新及更新的正确性。 最初进行cookie的设置测试。即在浏览器中对cookie是否禁用或cookie的应用级别进行测试。如在IE浏览器的“选项”性能中,“平安”选项卡和“隐衷”选项卡就能够对cookie进行设置 六、如何在浏览器中设置自定义cookie在网页即客户端中咱们也能够通过js代码来设置cookie。关上f12在console中输出 document.cookie="age=12; expires=Thu, 26 Feb 2116 11:50:25 GMT; domain=www.baidu.com; path=/"; 就可增加拜访百度的cookie, 具体cookie常识能够拜访:cookie详解_每天都记录一点点!-CSDN博客_cookie 接口测试工具能够应用国产接口测试和接口文档生成工具:apipost

January 22, 2021 · 1 min · jiezi

关于cookie:软件测试详解16cookie

一、什么是cookie“Cookie”是小量信息,由网络服务器发送进去以存储在网络浏览器上,从而下次这位举世无双的访客又回到该网络服务器时,可从该浏览器读回此信息。这是很有用的,让浏览器记住这位访客的特定信息,如上次访问的地位、破费的工夫或用户首选项(如样式表)。 Cookie 是个存储在浏览器目录的文本文件,当浏览器运行时,存储在 RAM 中。一旦你从该网站或网络服务器退出,Cookie 也可存储在计算机的硬驱上。当访客完结其浏览器对话时,即终止的所有 Cookie。 Cookie是指网站用于分别身份,进行会话(session)跟踪而存储在客户端的数据。它是有服务器产生并发送给客户端的。其用处是提供一个不便的性能以简化用户输出,节俭拜访页面的工夫。 Cookie能够由下列对象创立 Javascript、VBScript等HTML页面中的客户端脚本 应用MS win32 Internet函数(Internetsetcookie和Internetgetcookie)的win32程序 JSP/ASP等页面中的服务器端脚本。 二、禁用cookie可能会导致某些web零碎无奈失常运行 使用户无奈进行匿名拜访 使web零碎无奈跟踪用户的浏览习惯。 三、第一方跟第三方cookie第一方cookie是与宿主域名相关联的cookie 第三方cookie是来自任何其余域名的cookie 四、长久cookie和会话cookieCookie既能够存储在内存中(会话cookie),也能够存粗在硬盘中(长久cookie)长久cookie会被写入用户配置文件夹下的cookie文件夹,浏览器临时文件索引会应用指向长久cookie文件的指针进行更新。 五、cookie测试对于会话cookie,要测试其在不退出web零碎的状况下起作用,同时也要测试退出web零碎后不起作用,即从新登录时没有上次操作的痕迹。 对于长久cookie,要测试其在退出web零碎后依然起作用,即从新登录时保留上次操作的痕迹。 对于长久cookie,还要进行cookie的更新测试,即更新页面信息或者进行其余操作后,再次登录,查看cookie是否更新及更新的正确性。 最初进行cookie的设置测试。即在浏览器中对cookie是否禁用或cookie的应用级别进行测试。如在IE浏览器的“选项”性能中,“平安”选项卡和“隐衷”选项卡就能够对cookie进行设置 六、如何在浏览器中设置自定义cookie在网页即客户端中咱们也能够通过js代码来设置cookie。关上f12在console中输出 document.cookie="age=12; expires=Thu, 26 Feb 2116 11:50:25 GMT; domain=www.baidu.com; path=/"; 就可增加拜访百度的cookie, 具体cookie常识能够拜访:cookie详解_每天都记录一点点!-CSDN博客_cookie 接口测试工具能够应用国产接口测试和接口文档生成工具:apipost

January 22, 2021 · 1 min · jiezi

关于cookie:前端面试每日-31-第629天

明天的知识点 (2021.01.04) —— 第629天 (我也要出题)[html] 写一个滚动吸顶的布局[css] 在Less中怎么应用变量?如何定义?[js] 写一个办法监听指定cookie的变动[软技能] 上传文件能应用GET申请吗?为什么?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!!欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨!心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

January 4, 2021 · 1 min · jiezi

关于cookie:Cook-Cookie-我把-SameSite-给你炖烂了

什么样的常识,最好吃?入口即化的 啰里吧嗦的结尾SameSite cookie 推出已一年无余,本人看了不少文章,也撞了不少南墙,所以还是那句好忘性不如烂笔头。你可能感觉本人懂了,但试着讲进去,能力晓得本人是否真的懂了。 列一列本人看过的文章: 带你入门的阮老师:https://www.ruanyifeng.com/bl...很长很官网的文章:https://web.dev/samesite-cook...SameSite 诞生的草案:https://tools.ietf.org/html/d...SameSite 开始发威的草案:https://tools.ietf.org/html/d...RFC 6265 Cookie 标准,HTTP State Management Mechanism:https://tools.ietf.org/html/r...走进SameSite和新冠一起火了的SameSiteSameSite Cookie行为更新去年就开始被提上日程,2020年2月随着Chrome 80的推出,这个属性开始正式失效,但因为3月份正是寰球新冠肆虐的时候,过后的维护者都还活在新冠的恐怖之下,网站没法及时更新,这项政策导致很多网站瘫痪,chrome官网又在4月进行了回滚,临时终止了这项策略。直到2020年7月14日Chrome 84稳定版开始,从新复原SameSite cookie策略,并且会逐渐部署到Chrome 80以及以上的版本中。 如果你晓得CSRF,那你就晓得这项攻打真正的外围就是利用 cookie 主动携带的行为(进一步讲就是跨站携带cookie)。 之所以会跨站携带,是因为起初 cookie 的标准中并没有 SameSite 这个属性;直到2016年first-party-cookies草案的推出,但并有多少人真正去用,而浏览器这边的实现也默认是SameSite=None,所以对开发者并没有什么影响,天然就没有引起多大的关注,至多不如这次,而提案初衷:改善平安和隐衷泄露的问题。成果天然就不是很现实。 为了解决这些问题,一个新的草案:Incrementally Better Cookies,在草案的结尾,就间接说道: This document proposes two changes to cookies inspired by the properties of the HTTP State Tokens mechanism proposed in [I-D.west-http-state-tokens]. First, cookies should be treated as "SameSite=Lax" by default. Second, cookies that explicitly assert "SameSite=None" in order to enable cross-site delivery should also be marked as "Secure"翻译成中文就是两个改良 : ...

December 30, 2020 · 1 min · jiezi

关于cookie:第三阶段-Day19-用户回显-封装Cookie-商品远程调用-购物车模块-CRUD操作

1.用户模块实现1.1 用户信息回显1.1.1 页面URL剖析 1.1.2 查看页面JS 1.1.3 编辑JT-SSO的Controller`/** * 业务实现: * 1.用户通过cookie信息查问用户数据. 通过ticket获取redis中的业务数据. * 2.url申请: http://sso.jt.com/user/query/+ _ticket * 3.参数: 参数在url中. 利用restFul获取 * 4.返回值要求: SysResult对象(userJSON) */ @RequestMapping("/query/{ticket}") public JSONPObject findUserByTicket(@PathVariable String ticket, HttpServletResponse response, String callback){ String userJSON = jedisCluster.get(ticket); //1.lru算法清空数据 2.有可能cookie信息有误 if(StringUtils.isEmpty(userJSON)){ //2.应该删除cookie信息. Cookie cookie = new Cookie("JT_TICKET", ""); cookie.setMaxAge(0); cookie.setDomain("jt.com"); cookie.setPath("/"); response.addCookie(cookie); return new JSONPObject(callback,SysResult.fail()); } return new JSONPObject(callback,SysResult.success(userJSON)); }` 1.2 编辑Cookie工具API`package com.jt.util;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class CookieUtil { //1.新增cookie public static void addCookie(HttpServletResponse response,String cookieName, String cookieValue, int seconds, String domain){ Cookie cookie = new Cookie(cookieName,cookieValue); cookie.setMaxAge(seconds); cookie.setDomain(domain); cookie.setPath("/"); response.addCookie(cookie); } //2.依据name查问value的值 public static String getCookieValue(HttpServletRequest request,String cookieName){ Cookie[] cookies = request.getCookies(); if(cookies !=null && cookies.length >0){ for (Cookie cookie : cookies){ if(cookieName.equals(cookie.getName())){ return cookie.getValue(); } } } return null; } //3.删除cookie public static void deleteCookie(HttpServletResponse response,String cookieName,String domain){ addCookie(response,cookieName,"",0, domain); }}` 1.3 用户退出操作1.3.1 业务阐明如果用户点击退出操作, 首先应该删除Redis中的数据 其次删除Cookie中的数据 之后重定向到零碎首页. ...

November 9, 2020 · 4 min · jiezi

关于cookie:cookie和session-的简介及区别

一、会话什么是会话呢???当浏览器发送申请拜访服务器开始,始终到拜访服务器完结,浏览器敞开为止,这期间浏览器和服务器之间产生的所有申请和响应加在一起,就称之为浏览器和服务器之间的一次会话。在一次会话中往往会产生一些数据,而这些数据往往是须要咱们保存起来的。 那么如何保留会话中产生的数据呢? !!能够应用cookie或session保留会话中产生的数据。 二、cookiecookie的工作原理 (1)Cookie是将会话中产生的数据保留在浏览器客户端,是客户端技术(2)Cookie是基于两个头进行工作的: 别离是Set-Cookie响应头和Cookie申请头:服务器在响应中给浏览器发送Cookie时,是通过Set-Cookie响应头将cookie从服务器端发送给客户端浏览器,让浏览器保留到外部;而浏览器外部一旦保留了cookie,当前浏览器每次拜访服务器时,都会通过cookie申请头,将cookie信息从浏览器再带回服务器端,如果服务器端须要,能够获取申请中的cookie,从cookie中获取保留的数据,从而实现某些性能。 cookie的API及利用 1、创立Cookie对象`Cookie c = new Cookie(String name, String value);// 创立Cookie的同时须要制订Cookie的名字 以及 cookie中要保留的值(数据)` 2、将Cookie增加到response响应中`response.addCookie( Cookie c );// 将Cookie增加到response响应中, 由服务器负责将cookie信息发送给浏览器, 再由浏览器保留到外部// 能够屡次调用该办法, 增加一个以上的cookie` 3、获取申请中的所有cookie对象组成的数组`Cookie[] cs = request.getCookies();// 获取申请中携带的所有cookie组成的cookie对象数组;// 如果申请中没有携带任何cookie, 调用该办法会返回null值。`4、删除浏览器中的Cookie在cookie的API中没有提供间接将cookie删除的办法, 能够通过别的形式间接删除cookie代码示例:删除名称为cart的cookie: 能够向浏览器再发送一个同名的cookie(即名称也叫cart),并设置cookie的最大生存工夫为零,因为浏览器是依据cookie的名字来辨别cookie,如果前后两次向浏览器发送同名的cookie,后发送的cookie会笼罩之前发送的cookie,而后发送的cookie也设置了生存工夫为零,因而浏览器收到后也会立刻删除!`//创立一个名称为cart的cookieCookie c = new Cookie( "cart" , "" );//设置cookie的最大生存工夫为零c.setMaxAge( 0 );//将cookie增加到响应中,发送给浏览器response.addCookie( c );`5、Cookie的罕用办法`cookie.getName() //获取cookie的名字cookie.getValue() //获取cookie中保留的值cookie.setValue() //设置/批改cookie中保留的值(没有setName办法,因为cookie的名字无奈批改)cookie.setMaxAge() //设置cookie的最大生存工夫` 三、sessionsession的工作原理(1)session保留在服务器端,属于服务器端技术(2)session是一个域对象,session中保留了一个map汇合,往session中存数据,其实就是将数据保留到session的map汇合中(3)通过session.setAttribute办法能够将数据保留到session对象map汇合中,通过session.getAttribute办法能够将数据从session中取出来。 session作为域对象应用 Session是一个域对象,因而session中也提供了存取数据的办法。session.setAttribute(String attrName, Object attrValue);//往session域中增加一个域属性, 属性名只能是字符串, 属性值能够是任意类型session.getAttribute(String attrName);//依据属性名获取session域中的属性值, 返回值是一个Object类型 如何获取session对象:HttpSession session = request.getSession(); // 获取一个session对象, 如果在服务器外部有以后浏览器对应的session对象,则间接返回该session对象; 如果在服务器外部没有对应session, 则会创立一个新的session对象再返回。 ...

November 9, 2020 · 1 min · jiezi

关于cookie:113

1.拉取近程代码2.在本地实现代码合并3.从新提交推送代码zuul会过滤敏感http协定头,默认过滤以下协定头:1.Cookie 2.Set-Cookie 3.Authorization 能够设置zuul不过滤这些协定头zuul: sensitive-headers:rdb快照 aof数据操作记录zipkin 服务产生的链路日志发送到zikpin服务,进行图表展示 两种发送形式 1.间接连贯zipkin,向zipkin发送 2.通过音讯服务直达发送

November 6, 2020 · 1 min · jiezi

关于cookie:cookie相关方法封装

原文地址:占位作者:Fw恶龙本文首发于:思否var CookieUtil = { get: function(name) { var reg = new RegExp('(^| )' + encodeURIComponent(name) + '=([^;]*)(;|$)') var arr = document.cookie.match(reg); if(arr != null) { return decodeURIComponent(arr[2]) } else { return null } }, set: function(name, value, options) { options = options || {}; var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value); var maxAge = ''; var fixIE = ''; if(typeof(options.maxAge) != 'undefined') { maxAge = '; max-age=' + (options.maxAge * 60 * 60); if(options.fixIE) { fixIE = this.fixIE(options.maxAge * 60 * 60 * 1000); } } var path = ''; // 设置门路 if(typeof(options.path) != 'undefined') { path = '; path=' + options.path; } var domain = ''; // 设置域 if(typeof(options.domain) != 'undefined') { domain = '; domain=' + options.domain; } var secure = ''; // 设置安全措施,为 true 则间接设置,否则为空 if(options.secure || false) { secure = '; secure' } console.log([cookieText, maxAge, fixIE, path, domain, secure].join('')); document.cookie = [cookieText, maxAge, fixIE, path, domain, secure].join(''); }, fixIE: function(time) { // 修复IE不兼容max-age的问题 var d = new Date(); d.setTime(d.getTime() + time); return '; expires=' + d.toGMTString() }, clear: function(name) { this.set(name, '', { maxAge: 0 }) }};CookieUtil.set('name', '恶龙');console.log(CookieUtil.get('name'));CookieUtil.clear('name');console.log(CookieUtil.get('name'));未测试IE各个版本,Edge是反对max-age的,查问Can I Use显示近几个版本IE反对该属性。相干链接Http Cookies 中 Max-age 和 Expires 有什么区别?聊聊 JavaScript 中的 Date 对象JavaScript权威指南(第七版)-第23章 离线利用与离线存储-23.3 数据存储-23.3.1 CookieJavaScript高级程序设计第三版-第20章 客户端存储-20.2 cookie

October 22, 2020 · 1 min · jiezi

关于cookie:1021

1.用户模块实现1.1用户信息回显1.页面URL剖析 2.查看页面JS 3.编辑单点登录的Controller 1.2编辑Cookie工具API 1.3用户退出操作1.3.1 业务阐明如果用户点击退出操作, 首先应该删除Redis中的数据 其次删除Cookie中的数据 之后重定向到零碎首页. 1.3.2 URL剖析 编辑UserController 2实现商品详情展示2.1业务阐明 2.2重构JT-MANAGE2.2.1创立接口 2.2.2 编辑Dubbo实现类 编辑YML配置文件编辑ItemController

October 21, 2020 · 1 min · jiezi

关于cookie:cookies-sessionStorage和localStorage

cookies:数据大小不超过4k,cookies过期之前始终无效,会主动传递到服务器sessionStorage:存储大小绝对cookies大得多(5M或更大),敞开浏览器窗口后主动删除,仅存本地localStorage:存储大小绝对cookies大得多(5M或更大),除非手动删除,关浏览器后不会删除,仅存本地

September 21, 2020 · 1 min · jiezi

关于cookie:小白对cookiesession基础了解

Cookie、Session什么是会话?浏览器在申请拜访服务器开始,始终到拜访浏览器完结,浏览器敞开为止,这期间浏览器和服务器之间产生的所有申请和响应加在一起,就称为浏览器和服务器之间的一次会话。在一次会话中往往会产生一些数据,而这些数据须要咱们保存起来,例:*比方在没有登录时,将商品记录到购物车,其实就是将商品信息存入到了coocie或者session中。能够用cookie或者session保留会话中产生的数据 Cookie的工作原理1:Cookie是将会话中产生的数据保留在客户端,属于客户端技术;2:Cookie是基于两个头进行工作的:Set-Cookie响应头和Cookie申请头;3:通过Set-Cookie响应头将Cookie从服务器发送到浏览器,让浏览器保留到外部;而浏览器一旦保留了Cookie,当前浏览器每次拜访服务器时,都会通过Cookie申请头,将Cookie信息带回到服务器中。在须要时,在服务器端能够获取申请中Cookie的数据,从而实现一些性能; Cookie中API的利用1.创立Cookie对象 Cookie cookie = new Cookie(String name,Stringvalue);// 创立cookie的同时须要指定cookie的名字和cookie要保留的值// Cookie的名字一旦指定后,就无奈批改!2.将Cookie增加到response响应中 response.addCookie(Cookie cookie);// 将cookie增加到响应中,由服务器负责将cookie信息发送给浏览器,再由浏览器保留到外部(能够屡次调用该办法,增加一个以上的cookie3.获取申请中的所有Cookie对象组成的数组 Cookie[] cookie = request.getCookies();// 获取申请中携带的所有cookie组成的cookie对象数组,如果申请中没有携带任何cookie,调用该办法会返回null。4.删除浏览器中的Cookie // cookie的API中没有提供间接删除cookie的办法,能够通过别的形式间接删除cookie// 删除名称为cart的cookie:能够向浏览器再发送一个同名的cookie(即名称也叫做cart),并设置cookie的最大生存工夫为零,因为浏览器是依据cookie的名字来辨别cookie,如果前后两次向浏览器发送同名的cookie,后发送的cookie会笼罩之前发送的cookie。而后发送的cookie设置了生存工夫为零,因而浏览器收到后也会立刻删除!5.Cookie的罕用办法: cookie.getName(); // 获取cookie的名字cookie.getValue(); // 获取cookie中保留的值cookie.setValue(); // 设置/批改cookie中保留的值(没有setName办法,因为cookie的名字无奈批改)cookie.setMaxAge(); //设置cookie的最大生存工夫(如果不设置,cookie默认在一次会话完结时销毁!)6.设置Cookie最大的生存工夫(SetMaxAge): cookie。setMaxAge(60) //单位为秒示例: Session原理及利用Session的工作原理1:Session是将会话中的产生的数据保留在服务器端,属于服务器端技术;2:Session是一个域对象,Seesion中也保留了一个map汇合,往Session中存数据,其实就是将数据保留到Session指定map汇合中;3:通过session.setAttribute()办法,能够将数据存入到Session中,通过session.getAttribute()办法能够将数据从session中取出来; Session是一个域对象获取session对象: request.getSession()//获取一个Session对象,如果在服务器外部中由以后浏览器对应的session,则间接返回该session对象;如果没有对应的session,则会先创立一个新的session对象再返回;Session是一个域对象,在session中也保留了一个map汇合,并且sess中也提供了存取数据的办法,如下: session.setAttribute(String attrName,Object attrValue);//往session域中增加一个域属性,属性名必须为字符串类型,属性值能够为任意类型session。setAttribute(String attrName);//依据属性名能够获取域中的属性值,返回值是一个Object类型Session域对象的三大个性: (1)生命周期:创立session: 第一次调用request.getSession()办法时,会创立一个session对象。(当浏览器在服务器端没有对应的session时,调用request.getSession()办法,服务器会创立一个session对象)销毁session: 1.超时销毁:默认状况下,当超过30分钟没有拜访session时,session就会超时销毁(30分钟是默认工夫,能够批改);2.他杀: 调用session的invalidate办法时,会立刻销毁session;3.意外身亡: 1)当服务器非正常敞开时(硬件损坏,断电,内存溢出等导致服务器非正常敞开),session会随着服务器的敞开而销毁;2)当服务器失常敞开,在敞开之前,服务器会将外部的session对象序列化保留到服务器的work目录下,变为一个文件。这个过程叫做session的钝化(序列化);再次将服务器启动起来,钝化着的session会再次回到服务器,变为服务中的对象,这个过程叫做session的活化(反序列化); (2)作用范畴:在一次会话范畴内(获取到的都是同一个session对象) (3)次要性能:在整个会话范畴内实现数据的共享 总结 两者的区别Cookie和Session都属于会话技术,都能够保留会话中产生的数据,然而因为Cookie和Session的工作原理和特点不同,多以两者的利用场景也不同。 Cookie的特点:1.Cookie是将会话中产生的数据存入到浏览器客户端,属于客户端技术(JS能够拜访cookie)2.Cookie是将数据保留到浏览器客户端,容易随着用户的操作导致cookie失落或被窃取,因而cookie中保留的数据不太稳固,也不太平安3.cookie中数据存在浏览器中,对服务器端没有太大影响,能够将数据保留很长时间4.浏览器对cookie的大小和个数都有限度,个别每个站点给浏览器发送的cookie不超过20个,每个cookie大小不超过1KB 总结:cookie中适宜存须要长时间保留的,对安全性要求不高的数据;Session的特点:1.Session是将会话产生的内容存入到服务器端,属于服务器端技术2.session将数据存入到服务器端的session对象中,相对来说更加平安,稳固。不容易随着用户的操作而导致session中数据失落3.session是服务器端的对象,在并发量较高的时候,每一个浏览器客户端在服务端都要对应一个session对象,占用服务器的内存空间,影响效率 总结:session中适宜存储对安全性要求较高,但不须要长时间保留的数据;留神:cookie中保留中文数据的问题,Tomcat8.5及8.5当前的版本中曾经解决了该问题!留神:获取不到之前的session的问题将商品保留到session中后,敞开浏览器再关上浏览器,拜访服务器,此时获取不到之前的session。因为session是基于Cookie工作的。 在服务器创立一个session后,会为session调配一个举世无双的编号,称之为session的id,在此次响应时,服务器会将session的id以一个名称为JSESSIONID的cookie发送给浏览器保留到浏览器外部。 因为保留sessionid的cookie默认是会话级别的cookie,在浏览器敞开后,cookie会跟着销毁,sessionid也失落了。因而下次访问服务器,没有session的id就获取不到之前的session。也获取不到session中的商品信息 解决办法:咱们能够创立一个名称为JSESSIONID的cookie,其中保留session的ID,并设置cookie的最大存活工夫,让cookie保留到硬盘上(即便浏览器敞开,cookie也不会销毁),这样下次访问服务器时,还能够将sessionid带给服务器,服务器能够通过sessionid获取到之前的session。 从session中获取到商品信息

September 2, 2020 · 1 min · jiezi

关于cookie:互联网人必备知识cookie和session认证

用户认证在互联网倒退初期,Web基本上只是内容的浏览而已,服务器不须要记住每个浏览申请的状态,换句话说,服务器不须要有任何的状态信息,每次客户端的申请都是新的申请,这也是http无状态一个很显著的体现。随着互联网大潮的到来,尤其是像在线购物等这种和用户关系密切的零碎的大量衰亡,零碎须要辨识出用户,以便进行各种业务操作,这种需要给Http无状态这种个性一个强烈的冲击,所以最终的解决方案就是客户端申请的时候携带着一种标识,这种标识每个用户不同,这样服务端就能够依据这个标识辨别出不同的客户端用户了,这也就诞生了用户认证这个概念。 因为http协定是无状态的,所以基于http协定进行的认证,都须要依赖客户端上传的某种标识所谓身份认证,就是判断一个用户是否为非法用户的处理过程。以上是百科针对于用户认证的泛型定义,和认证相干的受权这里要顺便提一下,认证和受权是两个不同的概念,更是两个不同的阶段,绝大多数带有认证和受权的零碎,在用户操作流程上都是先进行认证,之后依据认证的后果再进行受权操作,有的初学者容易混同二者的概念。举一个很简答的栗子:一个OA零碎,在用户登录胜利之后,个别左侧都会依据以后用户的不同角色或者权限呈现不同操作的菜单树,其中用户登录这个过程就是认证的过程,而左侧的菜单树就是对以后用户的受权的一个具体表现形式(当然有的零碎可能不这样做,但不代表没有受权的流程)。 认证是用来证实一个用户身份的操作流程,受权是用来给以后用户赋予权限的操作流程。session认证通过上一篇文章,置信大家曾经明确了session和cookie的关系,如果你还没看过,我举荐还是看一下吧。 Session:在计算机中,尤其是在网络应用中,称为“会话管制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会失落,而是在整个用户会话中始终存在上来。当用户申请来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将主动创立一个Session对象。当会话过期或被放弃后,服务器将终止该会话。基于session的认证形式,最次要的一个特点就是:服务端存储着用户信息,客户端是通过携带一个sessionid的cookie来做session的标识。很多初期我的项目都喜爱采纳session的认证形式,这种形式对于疾速开发上线我的项目极为无利。每个客户端只须要保留一个cookie,然而服务端却须要保留成千上万的用户session信息,这无疑对服务端造成了很大的压力,尤其是当做了负载平衡之后,session的命中问题更为可怕。举个栗子:用户A登录零碎胜利,服务器A下发sessionid,session信息存储在服务器A上,如果当下次申请到服务器B上的时候,因为服务器B上没有session信息,所以就造成了未命中的景象,这也是session认证解决方案施行过程面临的一个问题。有问题就有解决方案,其中一个便是session复制,服务端的每个服务器都存储每个session的一个正本,这样申请无论达到哪个服务器,都能够胜利取到session信息,然而这样无疑增大了服务的存储压力,而且session在服务器之间的复制提早,session信息的更新同步、过期同步等操作都令人头疼。所以这种计划在肯定水平上其实并不举荐。 目前业界对于session存储的计划个别都偏向于集中式存储,像利用第三方的redis,Memcached把session信息都存储在同一个中央,所有的服务器都拜访这个中央的数据。这样就防止了session复制,同步等问题。然而引入了第三方,就意味着减少了一个第三方挂掉的可能性,所以当初都根本采纳第三方集群的计划来尽量减小这种可能性,把高可用性做到极致。另外说一点,因为大多数session机制是基于cookie的,在肯定水平上对于浏览器比拟敌对,然而对于很多挪动端利用其实并不是太敌对。 cookie认证因为session的认证信息保留在服务端,数据量达到肯定水平对服务器有肯定的压力,即便是采纳第三方的存储(比方redis)能够缓解这种问题,然而服务器和第三方存储的IO操作所破费的工夫有的时候也是很大的。在这种状况下,有的零碎放弃了session的认证形式,而间接采纳的最间接的cookie认证形式。 和session认证不同,用户的认证信息齐全存储在cookie中,换句话说用户的认证信息存储在客户端(这也是为什么不举荐在cookie认证中寄存敏感信息)。cookie认证这种形式的劣势就在于服务端没有了session存储的压力,每次辨认用户都只须要解析cookie的内容即可(解析cookie其实也须要破费工夫),相比拟第三方存储session的形式,缩小了一次网络IO操作,在肯定水平上进步了申请的响应速度,而且因为服务端处于无状态的模式,所以能够很不便的横向扩大。 基于cookie的认证形式也有很多毛病: cookie是存储在客户端的,所以在肯定水平上减少了能够伪造的几率,安全性上稍强劲一点。因为cookie在浏览中有跨域的拦截,所以在有跨域需要的时候,须要服务器做相应的配置。cookie是有长度限度的,所以不宜存储过长的信息。用户的客户端可能会禁用cookie,这个时候能够依附url传值来解决这个问题。服务端想要操作cookie认证信息的生效,比拟艰难,不像session认证那样不便。其实我司当初老的零碎都是利用的cookie验证形式,只不过cookie信息的加密算法很好,而且再加上全站https的策略,在肯定水平上安全性还是能够的(如果让我重构一次认证零碎,我不会抉择cookie认证)。 写在最初无论是基于session的还是基于cookie的认证形式,都须要客户端上传标识,都须要服务端下发这个标识,并且对这个标识进行加密。尽管加密,然而不法之人一旦拿到这个标识还是能够进行一系列非法操作,所以这个标识里边最好能加上起源IP和过期工夫这些属性,再配置上https,能够更加无效的爱护整个认证流程和数据。兴许还有更好的认证形式,敬请期待!! 更多精彩文章 分布式大并发系列架构设计系列趣学算法和数据结构系列设计模式系列

September 1, 2020 · 1 min · jiezi

大话2019前端面试题总结2期不要再问我cookie了

一、cookie面试常见题:1.Cookie是什么?★☆2.Cookie能做什么?★☆3.Cookie是怎么分类的?★☆4.Cookie的工作原理?★★★5.Cookie是怎么存储的?★☆6.每次访问网站时,是不是将所有的cookie都发送所有的站点?★7.cookie与缓存怎么取舍?★★8.cookie的缺点?★★9.如何使用cookie?★★★ 二、cookie面试常见题参考答案:1.Cookie是什么?★☆cookie时当前识别用户,实现持久化会话的最好方式。简单点说就是服务器知道正在和哪个客户端通信,以及保持与已识别出的客户端通信。Cookie的基本思想就是让浏览器积累一组服务器特有的信息,每次访问服务器时都将这些信息提供给它。 2.Cookie能做什么?★☆对连接另一端的用户有更多的了解,并且能在用户浏览页面时对其进行跟踪。 3.Cookie是怎么分类的?★☆(1)会话cookie。临时cookie,记录了用户访问站点时的设置和偏好。用户退出浏览器时,会话cookie就被删除了。(2)持久cookie。持久cookie的生存时间更长一些;它们存储在硬盘上,浏览器退出,计算机重启时它们仍然存在。通常会用持久cookie维护某个用户会周期性访问的站点的配置文件或登录名。唯一区别就是它们的过期时间。如果设置了Discard参数或没有设置Expires或没有设置Max-Age参数则说明这个cookie就是一个会话cookie。 4.Cookie的工作原理?★★★(1)用户首次访问Web站点时,Web服务器对用户一无所知。(2)Web服务器通过Set-Cookie首部将cookie存放到浏览器中的cookie数据库中。cookie中包含了N个键值对,例如Cookie: id=“1234”。cookie中可以包含任意信息,但它们通常都只包含一个服务器为了进行跟踪而产生的独特的识别码。(3)将来用户再次访问同一站点时,浏览器会从cookie数据库中挑中那个服务器设置的cookie,并在cookie请求首部中(Cookie: id=“1234”)将其传回给服务器。(4)服务器可以通过id="1234"这个键值对来查找服务器为其访问积累的信息(购物历史、地址信息等)。注意:cookie并不仅限与ID号。很多Web服务器都会将信息直接保存在cooki中。比如Cookie: name="Tom"; phone="111-2222" 5.Cookie是怎么存储的?★☆浏览器负责存储cookie信息。不同的浏览器会以不同的方式来存储cookie。有的浏览器用cookis.txt存储。有的浏览器存储在高速缓存目录下独立的文本文件中。 6.每次访问网站时,是不是将所有的cookie都发送所有的站点?★不是,浏览器通常只向每个站点发送2~3个cookie。原因如下:(1)对所有这些cookie字节进行传输会严重降低性能。(2)cookie中包含的时服务器特有的名值对,对大部分站点来说,大多数cookie都只是无法识别的无用数据。(3)将所有的cookie发送给所有站点会引发潜在的隐私问题,那些你并不信任的站点也会获得你只想发给其他站点的信息。 7.cookie与缓存怎么取舍?★★cookie是私有的,浏览器不希望得到的cookie和其他浏览器的cookie相同。一般缓存cookie图片而不缓存文本。 8.cookie的缺点?★★存在安全隐患。第三方Web站点使用持久cookie来跟踪用户就是对cookie一种最大的滥用。将这种做法与IP地址和Referer首部信息结合在一起,这些营销公司就可以构建起相当精确的用户档案和浏览模式信息。 9.如何使用cookie?★★★  Cookie首部用在浏览器发送的request中。它会将所有与域、路径和安全过滤器相匹配的未过期cookie都发送给这个站点。所有cookie都被组合到一个cookie首部中。 Cookie: Name1=Tom; Name2=Jerry如果你觉得这篇文章对你有所帮助,那就顺便点个赞吧,点赞收藏不迷路~ 黑芝麻哇,白芝麻发,黑芝麻白芝麻哇发哈! 前端哇发哈

August 19, 2019 · 1 min · jiezi

Vue-Webpack-重写cookie路径

webpack提供的反向代理服务器在开发阶段非常方便,几行简单的代码配置就可以使用反向代理功能,包括路径重写、cookie处理等。 项目开发阶段使用的API路径是 /admin,部署到线上是/,所以在开发过程中需要在proxyTable进行反向代理配置,将路径重写掉,路径重写代码如下(config/index.js): proxyTable: { '/admin': { target: 'http://127.0.0.1:8080', changeOrigin: true, pathRewrite: { '^/admin': '/admin2' }, }}启动项目之后进行登录,此时API请求成功,但是获取登录用户信息时发现cookie没有带过去。查看请求发现登录请求的Set-Cookie响应头中的Path是/admin2。但是咱们请求的路径是/admin,cookie当然不会生效。 查阅文档发现,proxyTable支持onProxyRes回调函数来自定义响应,流程是通过替换后端服务器设置的cookie-path来进行处理,代码如下: proxyTable: { '/admin': { target: 'http://127.0.0.1:8080', changeOrigin: true, pathRewrite: { '^/admin': '/lesson/admin' }, onProxyRes: function (proxyRes, req, res) { const cookies = proxyRes.headers['set-cookie'] if (cookies) { const newCookies = cookies.map(cookie => { return cookie.replace(/Path=\/admin2/, 'Path=/') }) delete proxyRes.headers['set-cookie'] proxyRes.headers['set-cookie'] = newCookies } } },},重启webpack之后重新登录,发现cookie的路径已经被重写到/了。

July 10, 2019 · 1 min · jiezi

Web-存储技术

一、背景介绍第一个Web存储的技术叫做Cookie,它是网站的身份证。是网站为了辨别用户身份,进行session(服务端的session)跟踪而存储在用户本地终端上的数据,也就是说它是存在电脑硬盘上的,一个很小的txt类型的文件。Cookie每次都会跟随http请求发送到服务端,也就是说每一个http请求都会带上我们的cookie数据,因此它存在一个安全性的问题。 cookie本身也是有很大的局限性的,首先它很小,主流的浏览器最大支持 4096 字节,除了最大字节的限制,每个网站的cookie个数(也就是每一个first每一个域)也是有限制的,一般浏览器是20个。除此之外,cookie还会默认跟随所有http请求发送,即使不需要使用这个cookie来鉴别用户但是它也是会跟随http请求发送的,这样就会造成一个网络资源的浪费。然后部分的浏览器还限制了总的cookie个数300个。 在cookie的诸多局限性下,Web Storage应运而生。Web Storage 解决了很多问题: 比如它支持存储大量数据,支持复杂的本地数据库,而且也不会默认跟随http请求。Web Storage主要是有四个: SessionStorageLocalStorageWebSQLindexedDB二、Cookie的简单介绍 Cookie是HTML4的一个标准,它一般不需要考虑兼容。它是网站的一个身份证,服务器可以针对不同用户,做出不同的响应。cookie存储在用户的机器上是一个纯文本,就是一个txt文件并不是一个脚本,它不能执行东西只负责记录。浏览器每次请求都会带上当前网站的cookie。 Cookie分为两种类型,一种呢是会话cookie,也就是临时性的cookie,退出浏览器或者是关闭即删除; 另一种叫持久cookie,它会一直存在,存在的时间由特定的过期时间或者是有效期来决定。 Cookie的域 Domain决定了当前的一个cookie的权限,哪一个域可以使用这个cookie。 Cookie的路径 Path,下面一个简单的例子: www.baidu.com id="123456" domain="www.baidu.com"www.baidu.com/user id="123456" user="eric" domain="www.baidu.com" path="/user/"www.baidu.com/search id="123456";www.baidu.com/user/search id="123456" user="eric";如上www.baidu.com设置了一个id等于123456,domain是www.baidu.com,然后另外一个跟第一个一样多设置了一个user,id相同,但是多了一个user=“Eric”,它的domain设置成了www.baidu.com,path就到了user下面。这两者设置完成之后,当我们访问www.baidu.com/search时百度只能拿到id,因为user="Eric"是属于user这个域下面的,也就是说在search下面是获取不到的,但是在www.baidu.com/user/search这个时候我们就可以获取到名叫Eric的user。Path也是一种权限的控制只是相较于域domain是低一级的。 Cookie的安全secure,如果这个属性为TRUE,那么网站只有在https的请求下面才会携带当前的cookie。 Cookie的HttpOnly这个属性如果为TRUE,那么就不允许JavaScript操作cookie。 因为cookie是存储在客户端一个独立的文件,因此服务器是无法分辨用户和攻击者的。关于cookie的目的分为两种:一种是跨站点脚本攻击,一种是跨站请求伪造。 三、SessionStorage key-value的键值对,是HTML5新增的一个会话存储对象。 SessionStorage是临时保存在同一窗口,也就是同一标签页的数据。如果当前标签页关闭了,那么SessionStorage也就失效了。这也是SessionStorage最显著的一个特点:单页标签限制。 除此之外,它还有的一些特点有: 同源策略,也就是在同一协议,同一主机名和同一端口下的同一tab只在本地存储,不会跟随http请求发送到服务器存储方式采用key-value键值对,这里面的value只能存字符串类型,如果存其他的会自动转换成字符串。存储上线限制达到了5MB,如果当前存储超出上限新的内容会把旧的内容覆盖但不会报错。属性: sessionStorage.length - 键值对数量sessionStorage.key(int index) -> nullsessionStorage.getItem(string key) -> nullsessionStorage[string key]sessionStorage.setItem(string key, string value)sessionStorage.removeItem(string key)sessionStorage.clear()Json对象 JSON.stringify()JSON.parse()四、LocalStorage LocalStorage也是在浏览器的Application下面有一个Local Storage,它和SessionStorage是十分相似的,同样是key-value键值对,也是HTML5的新增存储对象,它与SessionStorage的特点不同之处在于没有标签页的限制和在浏览器的无痕模式下LocalStorage是不允许读取的,永久性的存储,然后SessionStorage超出限制是覆盖不会报错而LocalStorage超出会报错。 特点: 同源策略,也就是在同一协议,同一主机名和同一端口下的同一tab没有标签页的限制只在本地存储,不会跟随http请求发送到服务器存储方式采用key-value键值对,这里面的value只能存字符串类型,如果存其他的会自动转换成字符串。存储上线限制达到了5MB,如果当前存储超出上限会报错。无痕模式下不可读取永久性存储属性: sessionStorage.length - 键值对数量sessionStorage.key(int index) -> nullsessionStorage.getItem(string key) -> nullsessionStorage[string key]sessionStorage.setItem(string key, string value)sessionStorage.removeItem(string key)sessionStorage.clear()注意事项:LocalStorage和SessionStorage在web view是不可靠的,web view指的是在开发混合APP的时候使用了浏览器来实现我们的APP,这个时候是不可靠的,因为在浏览器崩溃的情况下数据可能没有存进去。 另外一个在IOS浏览器中不可重复setItem,如果重复会报错,然后这个时候我们需要先removeItem再添加item。 监听storage的变化监听storage包括SessionStorage和LocalStorage。然后这里需要提到两个概念:同源和监听同源网页。 同源:协议、域名、端口三者相同,同源的情况下我们可以共享SessionStorage和LocalStorage。同源策略还禁止不同源执行任何脚本。 http://localhost:63342/simpleApp/app/index.html#/(协议) (域名) (端口) (路径)监听同源网页,但是同一网页是无效的 ...

July 8, 2019 · 3 min · jiezi

Response-Headers-的-SetCookie-前端读取不到

问题描述先看下后台返回的Set-Cookie字段:查看浏览器Cookies: 思路发现只有JESSIONID存入到了浏览器Storage中的Cookies。通过比较 Response Headers 中两个 set-cookie字段可以发现字段不同: JSESSIONID:path=/ZTEV-JWT-Token:Max-Age=1800; Expires=Wed, 26-Jun-2019 02:49:55 GMT解决让后台设置 ZTEV-JWT-Token 的时候也添加一个 path=/ 字段。 延伸其他原因我上面遇到的这个问题是因为后端没有设置path。当然还有一些其他的原因也会导致浏览器访问不到cookie,例如:设置了http-only、domain不匹配。 Set-Cookie指令<cookie-name>=<cookie-value>名称/值的形式。 cookie-name 可以是除了控制字符 (CTLs)、空格 (spaces) 或制表符 (tab)之外的任何 US-ASCII 字符。同时不能包含以下分隔字符: ( ) < > @ , ; : " / [ ] ? = { }.cookie-name 是可选的,如果存在的话,那么需要包含在双引号里面。支持除了控制字符(CTLs)、空格(whitespace)、双引号(double quotes)、逗号(comma)、分号(semicolon)以及反斜线(backslash)之外的任意 US-ASCII 字符。关于编码:许多应用会对 cookie 值按照URL编码(URL encoding)规则进行编码,但是按照 RFC 规范,这不是必须的。不过满足规范中对于 <cookie-value> 所允许使用的字符的要求是有用的。__Secure- 前缀 以 __Secure- 为前缀的 cookie(其中连接符是前缀的一部分),必须与 secure 属性一同设置,同时必须应用于安全页面(即使用 HTTPS 访问的页面)。__Host- 前缀 以 __Host- 为前缀的 cookie,必须与 secure 属性一同设置,必须应用于安全页面(即使用 HTTPS 访问的页面),必须不能设置 domain 属性 (也就不会发送给子域),同时 path 属性的值必须为“/”。Expires=<date> | 可选cookie 的最长有效时间,格林尼治标准时间。如果不传表示这是一个会话期 cookie。 ...

June 26, 2019 · 1 min · jiezi

web跨域及cookie学习

之前对于跨域相关的知识一致都很零碎,正好现在的代码中用到了跨域相关的,现在来对这些知识做一个汇总整理,方便自己查看,说不定也可能对你有所帮助。 本篇主要内容如下: 浏览器同源策略http 请求跨域http 请求跨域解决办法cookie 机制如何共享 cookie浏览器同源策略 相信很多人在 web 入门时,都被跨域问题折磨的死去活来。要想完全掌握跨域就得知道为什么会有跨域这个问题出现。 简单来说跨域问题是因为浏览器的同源策略导致的。那浏览器为什么要有同源策略呢? 当然是为了安全。没有同源策略限制的浏览器环境是非常危险的(即使有了同源策略也不是百分百安全),有兴趣的可以去了解了解CSRF和XSS攻击。 所谓的“同源”指的是“三个相同”: 协议相同。不能一个是 http 协议,一个是 https域名相同端口相同<!-- more --> 如果非同源页面有以下限制: LocalStore 和 IndexDB 无法读取。这两个显然是不能读取的,但是 cookie 有点不一样,放在后面单独说明DOM 无法获取,比如如法在页面 A 中通过 iframe 获取异源页面 B 的 DOMAJAX 请求无法读取(可以发送请求,但是无法读取到请求结果。比如在页面 A 中请求异源接口 B,请求会正常发出处理,但是在页面 A 中无法获取请求结果,除非响应头 Access-Control-Allow-Headers 中允许了页面 A 的源,这样就能读取到结果) 但是这里有个例外,所有带“src”属性的标签都可以跨域加载资源,不受同源策略的限制,这样你应该可以想到一个比较古老的跨域解决方案(JSONP),同时这个特性也会被用作 CSRF 攻击。 http 请求跨域 在前端开发中经常会遇到跨域的问题,比如前后端分离中前后端部署在不同的端口上,或者在前端页面中需要向另外一个服务请求数据,这些都会被跨域所阻挡。 目前主要有以下几种办法解决跨域问题: 关闭浏览器同源检查 这个太暴力,也太不安全了,不用考虑。 jsonp 实现跨域请求 前面说过了浏览器对于带 src 属性的标签都可以跨域的。因此 jsonp 的实现流失利用了这个特性,在页面中动态插入一个<script>标签,然后他的 src 属性就是接口调用地址,这样就能访问过去了,然后再讲返回内容特殊处理成立即执行的函数,这样就看起像进行了一次跨域请求。之所以不推荐这种方式,主要有以下两个原因: 实现复杂,且需要前后台同时修改才能实现只能进行 get 请求服务器设置运行跨域 这种方法只需要后台做处理便能实现跨域,前面说的 http 跨域请求是能够发出去的,只是不能接收,那我们只要在响应头Access-Control-Allow-Headers中加入允许请求的地址即可,以,分隔,同时*代表所有地址都允许。比如: ...

June 24, 2019 · 1 min · jiezi

使用apache的HttpClient进行http通讯隐藏的HTTP请求头部字段是如何自动被添加的

我们用apache的HttpClient这个库消费云端的Restful API时,一般都需要两次HTTP调用,第一次获得某种token,比如获取防止跨域请求伪造攻击Cross-site request forgery - CSRF的token,或者比如微信API的access token,第二次再进行真正的API消费。 通常情况下,第一次请求完毕后,服务器都会给客户端返回一些cookie字段,在第二次请求时,如果使用的是postman测试工具或者apache的HttpClient这个库,cookie字段都会自动被附加在第二次请求的HTTP头部。详情可以参考我写的另一篇博客:OData service parallel performance measurement – how to deal with XSRF token in Java Program and JMeterhttps://blogs.sap.com/2017/08... 本文就来介绍apache的HttpClient,在发送第二个Http请求时,是如何自动插入从第一个请求获得的服务器颁发的cookie的。 首先进入HttpClient的单步调试:InternalHttpClient.doExecute方法: 第85行的origheaders,即取出程序员在代码里指定的http请求头部字段,比如basic Authentication,content-type,token等等: 这个cookie是什么时候传进来的? 看来我们必须进入httpcore-4.4.3.jar这个apache HttpClient的实现里去调试。 经过观察发现,一旦我执行完204行的conn.sendRequestHeader方法,就能观察到Cookie被自动设置了,所以奥妙就在第204行里。 自动添加Content-Length头部字段: 由此可见Content-length是通过方法entity.getContentLength()自动计算出来的,因此我们程序员不必在自己的应用代码里重复这个计算动作。 自动加入host字段: 自动加入Connection: Keep-Alive UserAgent的自动填充:Apache-HttpClient/4.5.1, 这个也不用程序员操心。 终于到了我要找的RequestAddCookies这个HTTPRequestInterceptor了。光从这个类的字面意思就能猜到它和HTTP请求的Cookie有关。 新建一个Cookie,这个CookieOrigin构造函数里的hpst,path和secure标志位都是Chrome开发者工具的Cookie标签页里能看到。 从 Cookie Store里取出前一次请求中由服务器返回的Cookie: 这里把Cookie store里的cookie加到第二个请求的头部字段,谜底就这样解开了。 要获取更多Jerry的原创文章,请关注公众号"汪子熙":

June 22, 2019 · 1 min · jiezi

关于cookie-domain中的点前缀

今天同事遇到一个问题,大概描述如下: 浏览器已经接收指令,之前在一级域名下存储了相关的信息。这里为了简化问题,假设我们有两个应用A和B,域名分别为:a.b.com和c.a.b.com。(显然B是A的一个子域)。 上面的描述就是:在.b.com这个一级域名下,我们已经成功写入了一个cookie,假设为:b=level1。 在正常用户的浏览行为中,应用A会向自己的域下写入a=level2(domain:a.b.com)。 在A正常的页面中,有些场景会有异步的请求发出到B应用的页面(用于获取数据),合理的一种想法是:发送到B应用的请求,应该携带着上面的b=level1,a=level2这两个cookie信息到B应用的服务器去才对。但是,实际的情况是,b=level1被如愿携带上来,但是a=level2这个信息却被丢弃了!(确切的说是没有跟着request一起被发送到B的服务端)。 为啥?在访问子域应用时,不是父域名下的cookie都应该被携带上来吗?就像上面的b=level1那样? 其实,关于这点,在cookie的RFC规范中,并没有太明显的说明,至少我没有看到,即使又看了一遍RFC6265中关于Domain Matching的描述也是如此。 但实际的使用过程中,某个域下的cookie如果希望能够被他的子域具有可见性(即可以读取),必须要注意的一点是,应该保证这个cookie在被Set的时候,应该以"."开头。回到上面的例子,之所以a=level2这个cookie没有在用户浏览器请求B应用时被携带到B的server端,就是因为a=level2这个cookie的domain不是.a.b.com,而是a.b.com。 事实上,上面例子中的A应用,在向自己的域名下写入a=level2这个cookie时,压根就没有显示的设置domain这个属性,这样一来,浏览器接受到这个Set Cookie的请求时,就会以默认以当前应用的域名作为cookie的domain。(不过据说某些版本的Firefox到是会自作聪明的在当前域名的前面自动加上一个点,这个待验证!) 这一个小点的区别,还是很容易被忽略的,不过产生的浏览行为还是有细微差别的。(涉及到cookie是否上传,是否占用网络流量等) PS:关于上面说到的那个问题,stackoverflow上的这个有个截图,看着说明就直观很多了。

June 21, 2019 · 1 min · jiezi

多站点单点登录实现方案

今天写一篇关于多域名下单点登录的实现。 有这么个场景,公司下有多个不同域名的站点,我们期望用户在任意一个站点下登录后,在打开另外几个站点时,也是已经登录的状态,这么一过程就是单点登录。 因为多个站点都是用的同一套用户体系,所以单点登录可以免去用户重复登录,让用户在站点切换的时候更加流畅,甚至是无感知。 单点登录所要实现的就是,某一站点登录后,将其登录态会同步到其他另外几个站点。 我们分两部分,先说单个站点的登录流程,在说同步登录态的流程。 登录相关架构服务端采用 nodejs ,缓存采用 redis 。用户登录凭证采用基于 session 的 cookies 维系,采用 cookie 作为登录凭证是目前比较主流的方式。session 信息用 redis 承载,从数据层面上看, redis 中存储 session 对象的 key 便是 cookie 中的 valuekey是由 UUID 生成的唯一标识为了保证 session 与 cookie 保持对应, session 对象创建与修改都会触发服务端往浏览器写入 cookie登录流程我们先看单个站点的登录流程 用户首次打开站点,服务端生成 session 对象,此时 session 中没有用户信息,同时服务端往浏览器写入 cookie用户触发登录操作服务端校验参数处理登录逻辑后,生成用户信息,将用户信息写入 session 对象,更新缓存 redis我们来画个图,如下 同步登录态一个站点完成登录后,接下来就是如何让其他站点也拥有登录态。既然登录态是由 cookie 和 session 决定的,而 cookie 又是由 session 写入的,那么也就是说,只要把 session 同步到其它站点,其它站点只要获取到 session 后,就可以在该域名创建或更新 cookie ,这样一来,两个不同域名下的站点就拥有相同的登录信息了。 因此,同步登录态其实就是,如何同步 session 的问题。 而我们的 session 是采用 redis 作为载体,那么其他站点只要能获取到 redis 中存储的用户信息,不就可以创建自己的 session 对象了么? ...

June 15, 2019 · 1 min · jiezi

Nodejs中Koa2如何使用Session完成登录状态保持

项目要用到登录注册,就需要使用到Cookie和Session来保持登录状态,于是就简单研究了一下Cookie和Session的工作原理前面已经专门发过一篇帖子记录Cookie和Session的工作原理了,不明白的小伙伴可以看看Cookie、Session是如何保持登录状态的?。 使用Koa的Session中间件Koa是一个简洁的框架,把许多小功能都拆分成了中间件,用一个洋葱模型保证了中间件丰富的可拓展性,我们要使用Session来保持登录状态,就需要引用Session中间件。 安装Koa-Session中间件npm install koa-session --save如果需要使用TypeScript进行开发,则需要引入对应的TS类型声明 npm install @types/koa-session --save配置SessionKoa-Session需要做一些配置: const session_signed_key = ["some secret hurr"]; // 这个是配合signed属性的签名keyconst session_config = { key: 'koa:sess', /** cookie的key。 (默认是 koa:sess) */ maxAge: 4000, /** session 过期时间,以毫秒ms为单位计算 。*/ autoCommit: true, /** 自动提交到响应头。(默认是 true) */ overwrite: true, /** 是否允许重写 。(默认是 true) */ httpOnly: true, /** 是否设置HttpOnly,如果在Cookie中设置了"HttpOnly"属性,那么通过程序(JS脚本、Applet等)将无法读取到Cookie信息,这样能有效的防止XSS攻击。 (默认 true) */ signed: true, /** 是否签名。(默认是 true) */ rolling: true, /** 是否每次响应时刷新Session的有效期。(默认是 false) */ renew: false, /** 是否在Session快过期时刷新Session的有效期。(默认是 false) */};我们需要关注这几个配置: ...

May 6, 2019 · 2 min · jiezi

CookieSession是如何保持登录状态的

无论是web应用还是原生app应用,只要涉及网络连接,基本就离不开登录注册,我们注册完成后登录,这个状态就被保持下来了,我们下次打开app,应用就已经处于登录状态了,不需要我们重复登录,非常人性化,感觉服务器好像会“记得”我们每一个人一样,“记得”你来过,就不再要求你登录了。但其实计算机在这方面是很傻的,他不是自发“记得”我们的,这篇文章就来聊聊登录状态的保持是怎么实现的。HTTP协议要弄明白下面说的东西,就得先了解一下HTTP协议,繁琐的概念就不多赘述了,这里主要注意一点,_HTTP协议是无状态的_ ,什么叫无状态?我们从一个故事讲起: 你去一家水果店买水果,你看到他们的桃子很鲜美,于是你大赞了老板的桃子后并买了一斤。你回家尝了桃子后觉得非常好吃,你决定第二天继续购买。当你第二天开开心心的过来找老板,跟他说“你家的水果真的很好吃,再来一斤我昨天买的那个水果”,但是发现老板并不知道你昨天买过什么,于是你非常生气,跟老板说“我昨天还夸了很久你的水果,你怎么就不记得了?”一顿理论后你发现老板始终不记得你昨天干过什么事,最后你只好跟老板表明要买一斤桃子,交易后灰溜溜地离开。这个故事中的老板就是无状态的,对他来说,他只知道某个人要买什么东西,给了多少钱,要买什么水果,要找多少钱,对于过程中的其它信息如是“谁”来买,他不会记得,他只会针对买卖本身进行处理。 HTTP为什么无状态?首先什么是无状态?无状态就意味着每个请求之间的不会直接地相互影响,对于每个请求,同样的请求参数就会得到同样的结果。 回到HTTP协议中:最初的需求是请求HTML界面显示出静态网站,并不如现在那么复杂丰富,用户A点击某个网址浏览到的页面和用户B点击同样网址浏览到的页面是完全一模一样的,也就是服务器并不会对每个不同的人有特殊处理,服务器只对请求负责,不对发起请求的人负责。因此在HTTP设计中,每个请求都是独立的,每个请求中都包含了请求的所有数据,服务器只对请求和请求中携带的信息进行处理后返回特定结果。就如上面的那个水果店,老板只根据要买什么水果,水果多少钱,给了多少钱,进行处理,如果你跟他说你昨天与他交谈如何,他无动于衷,因为他完全不会记得这些事情,他完全不记得你曾来过。 HTTP如何保存登录状态?前面说到,HTTP是无状态的,每个请求之间的不会直接地相互影响。当我第一次调用用户名密码验证接口的时候,我需要输入账号、密码,服务器收到请求之后,就会根据账号去数据库取你的密码和你输入的密码进行比对,然后返回一个“密码正确”或“密码错误”。而问题在于当我第二次访问这个接口的时候,服务器依旧会执行他的职能:收到我发送的账号和密码,然后去数据库取数据进行比对后返回比对结果,对于服务器来说,每个请求不过是做了类似1+1是否等于2的判断然后返回结果而已。 我想要服务器能够记住我已经调用过一次登录接口并且以及成功了这个状态,应该怎么办? 我们可以很自然的想到,服务器不知道我们登录过的原因是因为没有记下来,要保持登录状态,只要让服务器记下来就可以了。我们可以在服务器专门设置一个存储,每次只要我验证账号和密码成功,就在这个存储里面存下“JabinGP登录成功”(这个JabinGP是用户名),这样我们服务器就记得JabinGP登录过了。 现在服务器已经知道JabinGP登录过了,但是这就够了吗?不够,因为HTTP请求并不会自动标明“这是JabinGP发起的请求”,所以我们还要做点工作让服务器能知道“这是JabinGP发起的请求”,然后服务器才好去存储下来的登录状态里面找“JabinGP登录成功”这个标志。怎么做?我们可以在调用请求的时候把自己的用户名加进请求的参数中,比如Get请求的URl参数、Post请求的请求Body中,这样服务器就可以根据我们的用户名判断我们有没有登录过了。 这样我们就初步的把登录状态保存了下来,其实这样的验证非常粗糙,所以基于这个思想,产生了下面的技术。 什么是Cookie?有很多品牌的Cookie,比如说蓝罐,广州酒家......什么?哦哦不好意思我搞错了,这个才是Cookie:Cookie就是存储在客户端的一小段数据,它可以存在硬盘中(永久Cookie),也可以存在内存中(临时Cookie) 什么是Session?Session是指服务器为某个会话开启的一段独特的存储空间(会话是指一个终端用户与交互系统进行通讯的过程,比如说我先登录,再查看我的邮箱内容,这个过程就是一个会话),一个Session用唯一的SessionId对应一段存储空间。 Cookie和Session是怎么用的?首先从概念上,Cookie和Session都是用来存东西的,问题在于它们都用来存什么,以及它们都做了什么?结合前面分析: Cookie的出现,代替了手动设置标识的步骤,因为我们可以把标识设置在Cookie里面,设置了Cookie后,Cookie就存在了,下次请求Cookie就会自动发送给服务器,这样我们就不用给每个请求都很麻烦地手动设置一个标识(比如前面分析中的用户名)。Session其实就是代替了在服务器存储状态的步骤,SessionId可以对应一段存储空间,这段空间对每个会话都是唯一的(比如我登录后,就产生了一个会话,也产生了一段存储空间,这段存储空间只被我当前的登录状态下的活动所使用,别人是用不到的),这样就可以确保每个登录状态都有对应的一小段存储空间来写入一些中间过程的数据。Cookie和Session的关系?看了上面的Cookie和Session的解释,以及Cookie和Session的使用,就可以发现它们两个其实完全不冲突,甚至这两者是需要相互配合的,因为Cookie是在客户端的存储,Session是在服务端的存储,Session的存储需要SessionId来一一对应,这样才不会出现xxx获得了JabinGP的登录状态然后用JabinGP的钱买东西这样的情况,SessionId则需要通过Cookie保存在用户客户端中,客户端通过保存在Cookie的SessionId来标识自己,表明“我就是JabinGP”。 到这里差不多就简单介绍完Cookie和Session以及登录状态的保持了,以上都是个人理解,用于个人学习记录,如有错误,请一定评论指正!

May 4, 2019 · 1 min · jiezi

BOM编程-cookie的赋值过期时间path路径封装以及与Storage的区别

cookie 不是window下面的属性,它是document下面的属性,cookie有一套专门的取值与赋值方法,与localStorage,sessionStorage不同特性cookie在document下面cookie可以设置一个时间自动去清除缓存,cookie如果不设置清除时间,则关闭浏览器自动清除。cookie它可以跨页面,但是不可以跨path路径(子路径可以取到父级路径的) ,前提是同域赋值新建一个文件夹,在文件夹下新建一个html页面 cookie3.html 和一个名为path2的文件夹在path2文件夹下新建 cookie4.html先看一下cookie: 赋值 // 普通赋值document.cookie = 'userName=Aihh' // 带过期时间 10s后清除cookievar d = new Date();d.setTime(Date.now() + 10*1000);document.cookie = 'userName=Aihh;Expires=' + d.toUTCString(); // 带访问路径document.cookie="age=18;path=/path2";注意: 设置过期时间使用的是0时区的时间,而我们北京时间是+8区的时间,所以这个时候要调用 toUTCString() 转换为标准时区的时间;path=/path2 设置只有在路径path2下面的网页才能访问(前提是同域),如果是 path=/ 则说明是根路径,任何同域页面都可以访问。赋值后打开 Application 查看 cookie 普通赋值 带过期时间,设置10s后过期 带路径,设置只有在路径path2下面的网页才能访问(前提是同域) 这个时候发现在 cookie3.html 找不到这个cookie 再打开path2下面的 cookie4.html ,就会看到这个cookie 封装cookie 属性和值是用 = 连接,属性之间用 ; 分隔,根据这个特点进行封装var CookieHelper = { addCookie: function (cookieName, cookieValue, exMinutes, cookiePath) { // 第三/四个参数,按需传参 var str = cookieName + "=" + cookieValue; if (arguments.length == 3) { let d = new Date(); d.setTime(Date.now() + exMinutes*60*1000); // 过期单位这里设置为分钟 str += ";Expires=" + d.toUTCString(); } if (arguments.length == 4) { str += ";path=" + cookiePath; } document.cookie = str; }, getCookie: function (cookieName) { var cookieArr = document.cookie.split(";"); for (let i in cookieArr) { var arr = cookieArr[i].split("="); if (arr[0].trim() == cookieName) { return arr[1]; } } }, removeCookie: function (cookieName) { document.cookie = cookieName + "= ;Expires=" + (new Date()).toUTCString(); }}与 localStorage,sessionStorage 的区别localStorage,sessionStorage在window下面, cookie在document下面localStorage要手动清除,sessionStorage关闭浏览器自动清除,而cookie可以设置一个时间自动去清除,cookie如果不设置清除时间,则关闭浏览器自动清除。localStorage可以跨同域页面,sessionStorage只能跨父子页面(通过 open() 打开的页面),cookie它可以跨页面,但是不可以跨path路径(子路径可以取到父级路径的) 。他们都不能跨域

April 30, 2019 · 1 min · jiezi

LocalStorage

先来几道面试题1、a.meituan.com 和 b.meituan.com 这两个域能够共享同一个 localStorage 吗?2、在 webview 中打开一个页面:i.meituan.com/home.html,点击一个按钮,调用 js 桥打开一个新的 webview:i.meituan.com/list.html,这两个分属不同webview的页面能共享同一个 localStorage 吗?3、如果 localStorage 存满了,再往里存东西,或者要存的东西超过了剩余容量,会发生什么?好了带着这些问题我们来往下看 1、基本方法// 用于存入数据window.localStorage.setItem('key', 'value');// 用于读取数据window.localStorage.getItem('key')//清除某个键名对应的键值localStorage.removeItem('key');// 用于清除所有保存的数据window.localStorage.clear()// localStorage.key()接受一个整数作为参数(从零开始),返回该位置对应的键值。localStorage.key(0)// Storage 接口储存的数据发生变化时,会触发 storage 事件,可以指定这个事件的监听函数。利用这个可以实现跨tab页通信window.addEventListener('storage', onStorageChange); 注意点:localStorage只能存String类型的字符串。存对象的时候会变成"[object Object]",因为({key:'xxx'}).toString()//"[object Object]"。这个时候我们可以通过JSON.stringify()。来帮我们实现转化。例如:localStorage.setItem('jsonString', JSON.stringify({key: 'mtt'}))2、作用域localStorage只要在相同的协议、相同的主机名、相同的端口下,就能读取/修改到同一份localStorage数据。这就回答了我们上面的前二个问题了,第一题:由于域名不同,不能进行共享。第二题:二个webview相当于同一个浏览器的不同标签页。所以可以共享。 与sessionStorage 、cookie 对比 localstorage在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在sessionStorage:不能在不同的浏览器窗口中共享,即使是同一个页面;cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在3、数据存储有效期localStorage理论上来说是永久有效的,即不主动清空的话就不会消失,即使保存的数据超出了浏览器所规定的大小,也不会把旧数据清空而只会报错(这里解答了上面的第三题)。但需要注意的是,在移动设备上的浏览器或各Native App用到的WebView里,localStorage都是不可靠的,可能会因为各种原因(比如说退出App、网络切换、内存不足等原因)被清空。 与sessionStorage 、cookie 对比 localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;sessionStorage:仅在当前浏览器窗口关闭之前有效;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭4、数据存储方面sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下$ 5、存储数据大小 cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大Web Storage拥有setItem、getItem、removeItem、clear等方法,不像cookie需要自己封装setCookie、getCookie等方法

April 23, 2019 · 1 min · jiezi

大话javascript 7期:Cookie、Session和Token的那些事儿

一、登录认证机制随着互联网的不断发展,无论是网站还是app,一般都会要求用户注册/登录。主要的登录方式有账户密码登录、第三方登录(微信登录、QQ登录、微博登录等)登录可分为三个阶段(登录验证、登录持续、退出登录);登录验证指客户端提供账号/密码(或第三方平台(微信、qq)获取openid/unionid)向服务器提出登录请求,服务器应答请求判断能否登录并返回相应数据;登录持续指客户端登录后, 服务器能够分辨出已登录的客户端,并为其持续提供登录权限的服务器。退出登录指客户端退出登录状态。二、保持登录持续状态的实现方式为什么要保持登录状态的持续?由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证方案:客户端登录成功后, 服务器为其分配一个唯一的凭证, 客户端每次请求资源时都带上这个凭证;实现方案cookie 会话机制session 会话机制token 会话机制三、Cookie、Session和TokenCookie(浏览器缓存)1.什么是CookieCookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。cookie其实是补充http协议的无状态性的缺点,底层是通过服务器端在http响应消息中增加set-cookie字段来将cookie信息发送给浏览器端,因为它只能存4k,一般用来存浏览器的身份信息,浏览器在访问服务器的某些资源的时候,会在http请求头中将cookie数据传给服务器,这样服务器就知道是谁请求的了,但是如果用户清除了cookie,那就啥都没有了2.Cookie的属性1、Expires:该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效(持久级别Cookie)。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效(会话级别Cookie),浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1;2、Domain: 我们现在有二个域名。域名A:b.f.com,域名B:d.f.com;显然域名A和域名B都是f.com的子域名如果我们在域名A中的Cookie的domain设置为.f.com,那么.f.com及其子域名都可以获取这个Cookie,即域名A和域名B都可以获取这个Cookie如果域名A没有显式设置Cookie的domain方法,那么domain就为.b.f.com,不一样的是,这时,域名A的子域名将无法获取这个CookieHttpOnly: 这个属性是面试的时候常考的,如果这个属性设置为true,就不能通过js脚本来获取cookie的值,能有效的防止xss攻击3.Cookie的操作封装cookie的常用操作方法设置cookie读取cookie删除cookievar cookieUtil = { getItem: function (name) { var cookieName = encodeURIComponent(name) + “=”, cookieStart = document.cookie.indexOf(cookieName), cookieValue = null; if (cookieStart > -1) { var cookieEnd = document.cookie.indexOf(’;’, cookieStart); if (cookieEnd == 1) { cookieEnd = document.cookie.length; } cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd)) } return cookieValue; }, setItem: function (name, value, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + “=” + encodeURIComponent(value); if (expires) { cookieText += “;expires=” + expires.toGMTString(); } if (path) { cookieText += “;path=” + path; } if (domain) { cookieText += “;domain=” + domain; } if (secure) { cookieText += “;secure”; } document.cookie = cookieText; }, unset: function (name, path, domain, secure) { this.setItem(name, “”, new Date(0), path, domain, secure) }}CookieUtil.setItem(“name”, ’tom’); // 设置cookieconsole.log(CookieUtil.getItem(’name’));//读取cookieCookieUtil.unset(“name”)//删除cookie4.Cookie防篡改机制因为Cookie是存储在客户端,用户可以随意修改。所以,存在一定的安全隐患。防篡改签名:服务器为每个Cookie项生成签名。如果用户篡改Cookie,则与签名无法对应上。以此,来判断数据是否被篡改。原理如下:服务端提供一个签名生成算法secret根据方法生成签名secret(wall)=34Yult8i将生成的签名放入对应的Cookie项username=wall|34Yult8i。其中,内容和签名用|隔开。服务端根据接收到的内容和签名,校验内容是否被篡改。举个栗子:比如服务器接收到请求中的Cookie项username=pony|34Yult8i,然后使用签名生成算法secret(pony)=666。 算法得到的签名666和请求中数据的签名不一致,则证明数据被篡改。Session(会话)1.什么是sessionsession是一种服务器机制,是存储在服务器上的信息,主要配合cookie完成浏览器的身份认证和状态存储方式多种多样,可以是服务器的内存中,或者是mongo数据库,redis内存数据库中。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。Session相对于cookie较安全点,当用户请求服务器的时候,服务器会把数据临时存下来,如果退出网站后,session会被销毁。Session是基于cookie实现的,浏览器第一次访问服务器时,服务器创建一个Session,同时生成一个唯一的会话key,即sessionID。接着sessionID及session分别作为key和value保存到缓存中,也可以保存到数据库中,然后服务器把sessionID通过set-cookie的方式写入浏览器,浏览器下次访问服务器时直接携带上cookie中的sessionID,服务器再根据sessionID找到对应的session进行匹配,来判断用户是否登录2.session鉴权过程【1】 客户端发起登录请求,服务器端创建session,并通过set-cookie将生成的sessionID写入的客户端的cookie中。【2】 在发起其他需要权限的接口的时候,客户端的请求体的Header部分会携带sessionID发送给服务端。然后根据这个sessionId去找服务器端保存的该客户端的session,然后判断该请求是否合法。3.cookie和session的区别Token(身份令牌)1.什么是tokentoken的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库浏览器第一次访问服务器,根据传过来的唯一标识userId,服务端会通过一些算法,如常用的HMAC-SHA256算法,然后加一个密钥,生成一个token,然后通过BASE64编码一下之后将这个token发送给客户端;客户端将token保存起来,下次请求时,带着token,服务器收到请求后,然后会用相同的算法和密钥去验证token,如果通过,执行业务操作,不通过,返回不通过信息;2.token生成方式浏览器第一次访问服务器时,服务器根据传过来的唯一标识userId,通过一些算法,加一个密钥,生成一个token,接着通过base64编码将token返回给客户端。客户端将token保存起来,下次请求时需要带着token,服务器收到请求后,用相同的算法和密钥去验证token3.token和session的区别token和session其实都是为了身份验证,session一般翻译为会话,而token更多的时候是翻译为令牌;session服务器会保存一份,可能保存到缓存,文件,数据库;同样,session和token都是有过期时间一说,都需要去管理过期时间;其实token与session的问题是一种时间与空间的博弈问题,session是空间换时间,而token是时间换空间。两者的选择要看具体情况而定。虽然确实都是“客户端记录,每次访问携带”,但 token 很容易设计为自包含的,也就是说,后端不需要记录什么东西,每次一个无状态请求,每次解密验证,每次当场得出合法 /非法的结论。这一切判断依据,除了固化在 CS 两端的一些逻辑之外,整个信息是自包含的。这才是真正的无状态。 而 sessionid ,一般都是一段随机字符串,需要到后端去检索 id 的有效性。万一服务器重启导致内存里的 session 没了呢?万一 redis 服务器挂了呢?sessionID是基于cookie实现的,而token不需要基于cookie。这就导致了sessionID只能用在浏览器上,对于原生的应用无法实现。原生的应用是不具备cookie的特性的。另外sessionID可以实现服务端注销会话,而token不能(当然你可以把用户登陆的token存入到redis中,但是不推荐token入库)4.token的优点Token作为用户认证的处理方式,有几个优点:无状态,可扩展:不会在服务端存储用户的登录状态,可以很容易的实现服务器的增减支持移动设备,对多类型客户端的支持良好支持跨程序调用,各个接口之间的调用更方便安全可靠5.什么是JSON Web TokenJSON web Token,简称JWT,本质是一个token,是一种紧凑的URL安全方法,用于在网络通信的双方之间传递。一般放在HTTP的headers参数里面的authorization里面,值的前面加Bearer关键字和空格。除此之外,也可以在url和request body中传递。Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。如果你觉得这篇文章对你有所帮助,那就顺便点个赞吧,点点关注不迷路~黑芝麻哇,白芝麻发,黑芝麻白芝麻哇发哈!前端哇发哈 ...

April 17, 2019 · 1 min · jiezi

Laravel 5.5 升级到 5.5.42 后遇到的 Cookie 序列化问题

最近手残升级了项目里 Laravel 的小版本号(v5.5.39 => v5.5.45),这不升级则已,一升级就出了问题!Sentry 平台上提示错误:openssl_encrypt() expects parameter 1 to be string, array given,具体报错记录如下:ErrorExceptionopenssl_encrypt() expects parameter 1 to be string, array givenvendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php in handleError at line 91vendor/sentry/sentry/lib/Raven/Breadcrumbs/ErrorHandler.php in handleError at line 34vendor/sentry/sentry/lib/Raven/Breadcrumbs/ErrorHandler.php in openssl_encryptvendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php in encrypt at line 91vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php in encrypt at line 139vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php in handle at line 66vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in Illuminate\Pipeline{closure} at line 149vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 53vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in then at line 102vendor/laravel/framework/src/Illuminate/Routing/Router.php in runRouteWithinStack at line 660vendor/laravel/framework/src/Illuminate/Routing/Router.php in runRoute at line 635vendor/laravel/framework/src/Illuminate/Routing/Router.php in dispatchToRoute at line 601vendor/laravel/framework/src/Illuminate/Routing/Router.php in dispatch at line 590vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php in Illuminate\Foundation\Http{closure} at line 176vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 30vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php in handle at line 58vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in Illuminate\Pipeline{closure} at line 149vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 53vendor/fideloper/proxy/src/TrustProxies.php in handle at line 56vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in Illuminate\Pipeline{closure} at line 149vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 53vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php in handle at line 30vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in Illuminate\Pipeline{closure} at line 149vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 53vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php in handle at line 30vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in Illuminate\Pipeline{closure} at line 149vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 53vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php in handle at line 27vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in Illuminate\Pipeline{closure} at line 149vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 53vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php in handle at line 46vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in Illuminate\Pipeline{closure} at line 149vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php in Illuminate\Routing{closure} at line 53vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php in then at line 102vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php in sendRequestThroughRouter at line 151vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php in handle at line 116public/index.php at line 55仔细查看上面的异常堆栈记录,并且进行断点调试,最终确定是由于 Laravel 5.5 升级小版本后 Cookie 加密的逻辑变动所导致的报错。查阅 Laravel 官方文档(Laravel 5.5 Upgrade Guide)后得知,Laravel 新版为了防止 PHP 对象的序列化/反序列化漏洞被利用,不再对 Cookie 值进行自动的序列化和反序列化处理。举个栗子:\Cookie::queue(‘user’, [‘id’ => 1, ’name’ => ‘admin’], 720, ‘/’)Laravel 更新到 v5.5.42 后,因为 Laravel 不再自动对 Cookie 值 [‘id’ => 1, ’name’ => ‘admin’] 进行序列化处理,而 openssl_encrypt ( string $data … ) 只能加密字符串数据,这个时候程序就会抛出错误:openssl_encrypt() expects parameter 1 to be string, array given。解决方法:新版里面在中间件 AppHttpMiddlewareEncryptCookies 新增静态属性 $serialize,当设置为 true 时可开启 Cookie 值的自动序列化和反序列化处理。/** * Indicates if cookies should be serialized. * * @var bool */protected static $serialize = true;【推荐】将 Cookie 值使用 JSON 函数编码成字符串后再进行存储(获取 Cookie 值后需调用 JSON 函数进行解码)。\Cookie::queue(‘user’, json_encode([‘id’ => 1, ’name’ => ‘admin’]), 720, ‘/’);-EOF-首发于知乎专栏《PHP和Laravel学习》:https://zhuanlan.zhihu.com/p/…扫码关注《PHP和Laravel学习》微信公众号: ...

April 9, 2019 · 2 min · jiezi

怎样与 CORS 和 cookie 打交道

翻译:疯狂的技术宅本文首发微信公众号:jingchengyideng欢迎关注,每天都给你推送新鲜的前端技术文章前言CORS 与 cookie 在前端是个非常重要的问题,不过在大多数情况下,因为前后端的 domain 一般是相同的,所以很少去关心这些问题。或者只是要求后端设置 Access-Control-Allow-Origin: * 就行了,很少去了解背后运作的机制。针对这个问题,MDN 上有非常详细的解释,所以这篇文章主要在于整理重点和实际操作时经常出现的问题。同源策略(same-origin policy)为了防止 javascript 在网页上随意撒野,同源策略规定了某些特定的资源,代码必须在同源的情况下才可以存取。什么是同源呢?一份 document 的来源,由 protocol、host 和 port 来定义。也就是说如果文件1来自http://kalan.com,而文件2来自于 https://kalan.com 他们就不算是同源。那如果是子域名呢?像是 https://api.foobar.com 和 https://app.foobar.com。因为他们的 host 不同,所以也不算同一个源。而有些资源是本来就能够通过跨来源取得的:<img /><video />, <audio /><iframe />:可以通过定义 header 来防止他人嵌入通过 <link rel=“stylesheet” href /> 载入的CSS脚本<script src="" /> 载入的 Javascript通过代码发出的跨源请求则会受到同源策略的限制(如Fetch,XHR)。很显然,这样的规定太过严格了。如果都要限制在同源策略下的话,前后端开发会难以进行,也没办法用 XHR 的方式套用其他 SDK 的 API。也因此出现了 CORS( Cross-Origin Resource Sharing)的机制。CORS(跨源资源共享)很多人都觉得 CORS 是前端才需要具备的知识。不过 CORS 通常需要后端设定相关的 HTTP 头,并且了解背后的含义才有办法正确运作。那么跨来源请求是怎么运作的呢?主要是由两个 Header 来做相对的存取控制:请求当中的 Origin 和响应中的 Access-Control-Allow-Origin。只要发送请求时的 Origin 和响应头中 Access-Control-Allow-Origin 的值相同,或是 Access-Control-Allow-Origin: (代表允许任何域存取资源),此时就会放宽 CORS 的限制,允许存取跨域资源。如果不符合 CORS 策略的话,会显示下列信息:如果你尝试去读取回传的物件,还会得到警告。首先,如果我们按照提示中所说的,将 fetch mode 改成 no-cors 会发生什么事呢?的确,我们把烦人的错误信息给处理掉了,但是情况似乎并没有变好。no-cors并不是灵丹妙药,就算用了这个模式,CORS 也不会因此就打开大门,也就是你的请求并不会成功发出。也因此出现了 SyntaxError: Unexpected end of input 这个错误。这个模式通常是跟Service Worker搭配使用的。从上面这个实验当中可知,要解除CORS的封印只有一招,就是在服务器端加上正确的 Control-Access-Allow-Origin(host 必须跟原来相同或是)。另外,CORS 这个机制只会运作在 javascript 送出 XHR 或 fetch 时,一般 curl 或 postman 并没有这个机制,所以也因此常常在测试 API 端点时会忽略这件事,导致前后端在测试 API 时发生出入。有些跨来源请求不会发生 preflight,而有些请求则会,MDN上写的清清楚楚:必须是 GET,HEAD,POST 中的一种方法除了 user-agent 自动设置的 header 和特定的 header 之外,不包含其他 header 。可接受的header若有 Content-Type(注意是请求头,不是响应头),则必须是下列的值:application/x-www-form-encoded,text/plain,multipart/form-data也就是说如果不满足以上条件的话,就会发出 preflight 请求。我们试着把 Content-Type 改为 application/json 来测试一下(不能为 application/x-www-form-encoded,text/plain,multipart/form-data)。Preflight所谓的 preflight 就是请求会先用 HTTP 的 OPTION 方法去另外一个域敲门,确认没问题后才会送出真正的请求。一旦触发了这个条件,事情就会变得麻烦得多。必须加入一个 OPTIONS 的相同 api endpoint,并且设定 Access-Control-Allow-Origin 来符合 CORS 条件必须加入Access-Control-Allow-Headers,且必须包含所有不在条件内 header,否则无法通过。如果没有通过 preflight check 的话,会得到错误信息如下:Access to fetch at ‘http://localhost:3001/trigger-preflight’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.或是你没有在 OPTIONS 的响应头里加上 Access-Control-Allow-Origin:Access to fetch at ‘http://localhost:3001/trigger-preflight’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ’no-cors’ to fetch the resource with CORS disabled.如果成功的话,你会看到 network 里有两个请求,一个是 OPTIONS,另一个则是真正的请求。上图为 OPTION,下图为GET如果我们加上一个自制的头呢?根据MDN所定义的条件,也应该触发预检请求才对,我们加上一个X-Access-Token看看会发生什么事。的确无法通过preflight,如果要通过的话,必须再把 X-Access-Token 加入 Access-Control-Allow-Headers 中。附带身份验证的请求cookie 并不能跨域传递,也就是说不同 origin 来的 cookie 没办法互相传递及存取,不然就天下大乱了。不过如果你在 a 域送出了 b 域的请求,且 b 域回传了 cookie 的信息,那么在 a 域会以 b 域的形式储存一份cookie,如果没有设定 withCredentials 或是 credentials: ‘include’ 的话,就算服务器回传了 Set-Cookie,一样不会被写入。如下图:服务器回传Set-Cookie没有写入浏览器中在一般情况下如果再使用 b 域的 API,cookie 是不会自动被送出去的。这个情况下,你必须在 XHR 设定 withCredentials 或是 fetch 的选项中设置 { credentials: ‘include’ },因为这也是一个跨域请求,所以也必须按照 CORS 条件加入 Access-Control-Allow-Origin为了避免安全性的问题,器浏览还有规定 Access-Control-Allow-Origin不能为*。Access to fetch at ‘http://localhost:3001/cookie’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’.不过仅仅这样还是不够,器浏览会自动拒绝没有 Access-Control-Allow-Credentials 的响应,所以如果要将身份信息传到跨域的服务器中,必须额外加上 Access-Control-Allow-Credentials: true。如果这些都设定成功,应该会像下图这样,在 Request Cookie可以看到 cookie 被成功送出。Request Cookies 里有个 jack!好吧,如果你成功设定了这些东西,但还是有可能没办法把 cookie 送到服务器。那有可能会是以下几种情况:1.用户禁用了此域的 cookie可能使用者把你加入了黑名单,导致 cookie 无法成功送出解决方法:改域检讨自己为什么被用户封锁2.用户阻止了所有外部网站的cookie在Safari 中有时会开启“阻止所有Cookie”这一选项,这在调试时会让你尝到不少苦头。后记要处理 CORS 是件吃力不讨好的事情,尤其是有时在跑 CI/CD之前忘记加上 Access-Control-Allow-Origin 或是 Access-Control-Allow-Credentials,那么部署可能又是一天以后的事了。这次把一些常见的问题整理起来,希望以后如果再有类似的情形可以知道怎么处理。最后附上源代码。参考文章https://developer.mozilla.org…本文首发微信公众号:jingchengyideng欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章欢迎继续阅读本专栏其它高赞文章:12个令人惊叹的CSS实验项目世界顶级公司的前端面试都问些什么CSS Flexbox 可视化手册过节很无聊?还是用 JavaScript 写一个脑力小游戏吧!从设计者的角度看 ReactCSS粘性定位是怎样工作的一步步教你用HTML5 SVG实现动画效果程序员30岁前月薪达不到30K,该何去何从7个开放式的前端面试题React 教程:快速上手指南 ...

April 3, 2019 · 2 min · jiezi

Cookie和Session你不能不知道的秘密

1、cookie是什么由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。如下图:1.1、cookie的属性属性项属性项介绍Name一个唯一确定cookie的名称(cookie名称不区分大小写,实践中最好区分,因为一些服务器会区分),URL编码Value存储cookie的字符串值,值必须经过URL编码Expires过期时间,在这个时间点后Cookie失效Domain生成Cookie域名Path该Cookie是在当前那个路径下生成的Secure加密设置,设置他之后,只会在SSL连接时才会回传该Cookie这里我只要说二个点:1、Expires:该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效(持久级别Cookie)。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效(会话级别Cookie),浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1;2、Domain: 我们现在有二个域名。域名A:b.f.com,域名B:d.f.com;显然域名A和域名B都是f.com的子域名如果我们在域名A中的Cookie的domain设置为.f.com,那么.f.com及其子域名都可以获取这个Cookie,即域名A和域名B都可以获取这个Cookie如果域名A没有显式设置Cookie的domain方法,那么domain就为.b.f.com,不一样的是,这时,域名A的子域名将无法获取这个CookieHttpOnly: 这个属性是面试的时候常考的,如果这个属性设置为true,就不能通过js脚本来获取cookie的值,能有效的防止xss攻击1.2、cookie的操作由于js没有给原生的操作方法,我们可以简单地封装一下:var cookieUtil = { getItem: function (name) { var cookieName = encodeURIComponent(name) + “=”, cookieStart = document.cookie.indexOf(cookieName), cookieValue = null; if (cookieStart > -1) { var cookieEnd = document.cookie.indexOf(’;’, cookieStart); if (cookieEnd == 1) { cookieEnd = document.cookie.length; } cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd)) } return cookieValue; }, setItem: function (name, value, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + “=” + encodeURIComponent(value); if (expires) { cookieText += “;expires=” + expires.toGMTString(); } if (path) { cookieText += “;path=” + path; } if (domain) { cookieText += “;domain=” + domain; } if (secure) { cookieText += “;secure”; } document.cookie = cookieText; }, unset: function (name, path, domain, secure) { this.setItem(name, “”, new Date(0), path, domain, secure) }}CookieUtil.setItem(“name”, ’tom’); // 设置cookieconsole.log(CookieUtil.getItem(’name’));//读取cookieCookieUtil.unset(“name”)//删除cookie1.3、Cookie防篡改机制因为Cookie是存储在客户端,用户可以随意修改。所以,存在一定的安全隐患。防篡改签名:服务器为每个Cookie项生成签名。如果用户篡改Cookie,则与签名无法对应上。以此,来判断数据是否被篡改。原理如下:服务端提供一个签名生成算法secret根据方法生成签名secret(wall)=34Yult8i将生成的签名放入对应的Cookie项username=wall|34Yult8i。其中,内容和签名用|隔开。服务端根据接收到的内容和签名,校验内容是否被篡改。举个栗子:比如服务器接收到请求中的Cookie项username=pony|34Yult8i,然后使用签名生成算法secret(pony)=666。 算法得到的签名666和请求中数据的签名不一致,则证明数据被篡改。2、SessionSession: 是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中.为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。当客户端请求创建一个session的时候,服务器会先检查这个客户端的请求里是否已包含了一个session标识 - sessionId,如果已包含这个sessionId,则说明以前已经为此客户端创建过session,服务器就按照sessionId把这个session检索出来使用(如果检索不到,可能会新建一个)如果客户端请求(一般是通过cookie携带)不包含sessionId,则为此客户端创建一个session并且生成一个与此session相关联的sessionIdsessionId的值一般是一个既不会重复,又不容易被仿造的字符串,这个sessionId将被在本次响应中返回给客户端保存。保存sessionId的方式大多情况下用的是cookie。session 的运行依赖 session id,而 session id 是存在 cookie中的如果客户端的浏览器禁用了 Cookie怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,(在 url 中传递 session_id)即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。3、cookie与session的区别 cookiesession存储位置客户端服务器端存取方式只能保管ASCII字符串够存取任何类型的数据有效期不同Cookie可以设置过期时间属性JSESSIONID的过期时间默许为–1,只需关闭了阅读器该Session就会失效服务器压力Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存跨域支持上的不同Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。Session则不会支持跨域名访问。Session仅在他所在的域名内有效。区分路径cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎star对作者也是一种鼓励。参考Cookie防篡改机制彻底理解cookie,session,token ...

April 1, 2019 · 1 min · jiezi

十分钟轻松看懂Cookie

从经典的购物车说起发现很多地方在介绍cookie的作用时,都喜欢使用购物车的例子,那我们也不妨从这个例子开始说起。场景示例:有用户a和b,都登陆了某个购物网站,此时如果两个用户都点击了【查看购物车】按钮,那么此时服务器就同时收到了2个请求,请求的内容都是:“请告诉我我的购物车有什么商品”。现在问题来了——服务器怎么区分哪个请求对应哪个用户呢?其实这就是经常看到的那句话http协议是无状态的。为什么说无状态呢,因为http协议可以看成一种简单的应答模式:客户端发送一个请求,服务端返回相应的内容;客户端(可能不是同一个客户端了)又再发送一次请求,服务端(服务端还是同一个)就再返回相应的内容,那么服务端知道两次访问的客户端是不是同一个吗?显然是母鸡呀!为了解决这个问题,就要介绍今天的主角–Cookie。cookie登场可以联想一下生活中。我们如果去一家生意火爆的火锅店吃火锅的场景(我忽然有点想去吃个火锅再回来写了),这时如果有空座了,店员怎么知道在门口等候的顾客应该轮到谁了呢?很简单,在顾客等候之前,先发个号码牌,后面根据号码辨别身份。?!!看到这里,是不是觉得有点饿了?啊呸,是不是觉得灵光乍现,上面说的问题和这个场景不是如出一辙吗?所以,为了能够让会话可以被识别,http中也引入了一个号码牌——cookie的机制。(会话这个词出现地有点突兀,简单解释下:a用户登录购物网站之后,接下来发生的一系列请求,都应该属于服务端与a的会话)好了,原理大概说完了,那cookie具体怎么实现呢?很简单,放在http的头部(headers)。在前一篇讲状态码时,已经稍稍涉猎了一点http头部的相关知识,简单的来说http的头部是一个js对象,里面存放了一系列的键值对(key:value)用来表示各种信息,http的【请求】和【响应】都有头部,而cookie机制的实现,则是借助了其中的两个字段:Cookie和Set-Cookie,整个运行流程可以分成以下步骤:客户端发送一个http请求到服务端(我去告诉店员,我要吃火锅了)服务端响应该请求,并且在响应头中包含了Set-Cookie(店员回应我,并且给了我一张号码牌,告诉我有任何需要都带着号码牌来申请)客户端发送请求,请求头包含字段Cookie(我到店里后,呼叫服务员来一份雪花牛肉,并且告诉他,我的号码牌是6号)服务端根据请求中Cookie的内容响应。(服务员听到后,根据我的号码牌,给我给上了对应的菜)在上述过程中,可能同时也有其他号码牌的顾客在与服务员进行类似的交流过程,由于服务员发给每个顾客的号码牌上的数字都是唯一的,所以不必害怕弄混。cookie 的基本原理就是这么简单!当然,在生活中吃完饭我们就把号码牌丢掉了,下次来吃重新取号就行;但是在http请求中,cookie可以设置使用期限,比如说6个月后才过期。那么客户端接到这个内容后,就会把cookie缓存报本地的某个位置,之后如果访问相同的站点,就可以直接取出对应的cookie来使用。接下来我们看个实际案例(又到了紧张刺激的举例子环节,这次不仅有例子,还有精美配图,我觉得可以点个赞再走~)。首先,我们打开chrome浏览器的【设置】-【内容设置】-【cookie】(也可以在设置的顶部直接搜索),进入后可以查看【所有的cookie和网站数据】,看看segmengt这一条数据。里面一共有7个cookie,展开看详细内容,可以看到域名,脚本可访问、到期时间等属性,这些属性后面再介绍,为了看到整个流程,我们先清除这个站点下的cookie,当然也可以直接ctrl+shift+n打开一个隐身模式来直接测试。(隐身模式不会记录cookie,咳咳,我当然也是为了学习写代码才发现这个功能的!)然后我们打开segment站点,同时打开f12调试工具的network面板。可以看到这个请求(可以直接选doc类型查看,或者搜索框里搜segment.com快速过滤),可以看到这就对面前面说的第一个步骤:客户端发送请求,服务端响应并提供set-cookie(也就是发放号码牌的步骤)。接下来我们登录这个网站并且再次请求这个站点。此时响应头里已经不再有供set-cookie字段,因为cookie已经被缓存了(可以去前面的设置里再看看),而请求头里多了一个cookie字段。(这就是使用号码牌的步骤了)。接下来我们把面板的请求类型切换到xhr,再点点页面上的功能,比如收藏本文,或者给作者点赞、打赏(疯狂暗示)等等。 可以看到请求里都带上了cookie这个头部。直到cookie过期,或者下次我们又手动删除这个站点cookie之前,原有的cookie都可以继续使用。set-cookie和cookie接下来我们来说说set-cookie和cookie字段的具体内容。按照流程首先是来自服务端的set-cookie,直接copy一个前文的cookie下来,依此介绍:set-cookie: test_cookie=CheckForPermission; expires=Mon, 25-Feb-2019 00:28:09 GMT; path=/; domain=.doubleclick.net首先test_cookie=CheckForPermission,表示这个cookie的键值对,每个cookie都会有自己的名称和值expires=Mon, 25-Feb-2019 00:28:09 GMT表示cookie的有效期,这个值如果不指定,那么默认值为到浏览器关闭之前为止path=/,将服务器上的某个文件目录作为cookie的使用对象(这么抽象的解释肯定是书上说的),简单的来说,是指定服务端有权限访 问Cookie的路径,例如/session/,表示只有/session/下才可以访问cookie,默认为文档所在的目录。domain=.doubleclick.net,表示cookie所在的域。默认为创建cookie的域。也就是请求地址,比如前面的segment.comsecure,这个属性前面没有,表示只在https安全通信时才发送cookiehttpOnly,这个属性前面也没有,是用来限制使用脚本访问cookie的,设置了这个值后,无法在浏览器客户端使用js的document.cookie读取Cookie内容(页面内部是可以访问的),这个功能可以用来防止xss攻击中利用js劫持cookie。而cookie字段就简单的多:同样看一个实例:cookie:HPSESSID=web2~a667ecfoft7u5e3umvgam3vs65; Hm_lvt_e23800c454aa573c0ccb16b52665ac26=1551052787; _ga=GA1.2.113018985.1551052787; gid=GA1.2.1438865670.1551052787;直接以键值对的形式发送需要的cookie,使用分号分割表示多个cookie。使用cookie时,服务端会对发送来的cookie进行校验,校验的内容为过期时间(expire)、域(domain)、路径(path)、协议(是否secure),从而判断cookie是否有效。如果服务端已经发出了一个cookie,之后想修改cookie的值怎么办呢?那就要创建一个同名的cookie进行覆盖删除。同名的要求是除了name和expire以外的属性要和原来的cookie一致,否则会被当作不同的cookie保存。cookie的优缺点从前面的介绍我们至少可以看出cookie至少有以下几个优点:cookie的内容保存在客户端,不占用服务器资源有效时间可配置,使用灵活简单的键值对结构,较为轻量当然缺点也显而易见:cookie的长度一般会被限制在4k左右,超出部分会被丢弃浏览器可存储的cookie数量一般也是有数量限制的,ie8、Firefox限制为每个域名50个,chrome没有限制,但是由于规则1的存在,一个域名下cookie肯定也不能非常多,否则内容就超过4k了cookie功能可以被禁用,这就意味着基于cookie开发的功能要考虑如何应该这种情况不安全,容易被截取并篡改。某些数据必须存在服务端,比如下面即将介绍的跨设备数据同步。cookie的使用场景大部分讲cookie的文章都会提到这两个例子,但是很少有具体的说明大概是怎么实现的。这里做下简单的介绍。自动登录假设某网站登录时,提供了一个可以勾选的【7天内免登录】复选框,用户勾选并正确登录之后的流程大概是这样的:客户端发送请求到服务端,请求信息里包含用户名密码(当然一般是加密过的,但是我发现segment这里登录的时候居然直接把密码明文放在post的data里,应该提个改进类的bug过去给他--!)服务端接收请求后,创建一个id比如111,用于表示当前发送请求的客户端,并存在服务端的某个位置,简单点可以认为就存在一个名叫sessions的数组里面吧。之后,把这个id放在响应的set-cookie里面返回。例如:set-cookie:sessonId=111同时,服务端设定数组sessions中的保存的111在7天后删除客户端收到这个cookie之后保存,之后再次访问的时候都带上这个cookie,服务端接收到cookie里附带的sessionId=111后,去sessions数组查询是否含有111,如果发现有,说明当前用户可以自动登录,可以直接跳转到登录之后的页面如果不存在(已经被自动删除了),那么说明要重新登录(其实在上面已经悄咪咪的说了一丢丢session的内容,但是本着每次着重说明一个知识点、尽量剥离无关内容的原则,依然不在本文插入session的相关知识)未登录时的购物车本文已经多次提到购物车了,但是细心的朋友可以看到,这里的前面添加了“未登录”,那登录时候为什么不用呢?因为我们前面比较优缺点的时候,有提到cookie毕竟只能存储在发送请求的那个客户端设备,而电商网站一般是允许多终端登录的(x宝,x猫,x夕夕等),如果使用cookie来保存登录后的购物车内容,那更换设备的时候就无法查到了,所以登录状态下的购物车一般是存到数据库中的,只在离线的时候使用cookie的方式来处理比较合适。核心思路:首先初次进入页面时,客户端发送get请求,服务端在响应的set-cookie返回给客户端一个商品列表用户点击【将某商品添加到购物车】,客户端发送请求携带cookie发送请求,并且在请求体中携带商品id服务端接受到请求后,从请求头的cookie中取出商品列表,从请求体中取出本次商品id,然后查找商品列表是否包含该商品id,如果包含,那对应商品id增加;如果不存在,则从数据库查找该商品,并添加该商品信息和数量,并更新到cookie中如何读写cookiejs读写cookie的方法到处都有,随便搜索下应该就能找到,本文还是着重于说明cookie的原理,就不在此赘述了。小结本文对cookie的原理和应用场景进行了说明,依然延续以往的“一篇文章只说一件事”的习惯(程序员的事,怎么能叫偷懒呢,这叫模块化封装)。希望能对看完的同学有所帮助(就算是只收获了表情包也是极好的)。顺便说一下,前一篇文章似乎效果不错,骗到了很多收藏和点赞,非常开心(再次疯狂暗示)惯例:如果内容有错误的地方欢迎指出(觉得看着不理解不舒服想吐槽也完全没问题);如果有帮助,欢迎点赞和收藏,转载请征得同意后著明出处,如果有问题也欢迎私信交流,主页有邮箱地址

February 25, 2019 · 1 min · jiezi

PHP面试常考之会话控制

你好,是我琉忆,欢迎您来到PHP面试专栏。本周(2019.2-25至3-1)的一三五更新的文章如下:周一:PHP面试常考之会话控制周三:PHP面试常考之网络协议周五:PHP面试常考题之会话控制和网络协议以下正文的内容来自《PHP程序员面试笔试宝典》书籍,如果转载请保留出处:最近是换工作潮自己刻意“汇总整理了11篇带解析的PHP面试题的文档”,已上传百度云,关注公众号:“琉忆编程库”,回复:“php”,下载链接我发给你。一、sessionPHP的会话也称为Session。PHP在操作Session时,当用户登录或访问一些初始页面时服务器会为客户端分配一个SessionID。SessionID是一个加密的随机数字,在Session的生命周期中保存在客户端。它可以保存在用户机器的Cookie中,也可以通过URL在网络中进行传输。用户通过SessionID可以注册一些特殊的变量,称为会话变量,这些变量的数据保存在服务器端。在一次特定的网站连接中,如果客户端可以通过Cookie或URL找到SessionID,那么服务器就可以根据客户端传来的SessionID访问会话保存在服务器端的会话变量。Session的生命周期只在一次特定的网站连接中有效,当关闭浏览器后,Session会自动失效,之前注册的会话变量也不能再使用。具体的使用步骤如下:1)初始化会话。在实现会话功能之前必须要初始化会话,初始化会话使用session_start()函数。bool session_start(void)该函数将检查SessionID是否存在,如果不存在,则创建一个,并且能够使用预定义数组$_SESSION进行访问。如果启动会话成功,则函数返回TRUE,否则返回FALSE。会话启动后就可以载入该会话已经注册的会话变量以便使用。2)注册会话变量。自PHP 4.1以后,会话变量保存在预定义数组$_SESSION中,所以可以以直接定义数组单元的方式来定义一个会话变量,格式如下:$_SESSION[“键名”]=“值”;会话变量定义后被记录在服务器中,并对该变量的值进行跟踪,直到会话结束或手动注销该变量。3)访问会话变量。要在一个脚本中访问会话变量,首先要使用session_start()函数启动一个会话。之后就可以使用$_SESSION数组访问该变量了。4)销毁会话变量。会话变量使用完后,删除已经注册的会话变量以减少对服务器资源的占用。删除会话变量使用unset()函数,语法格式如下:void unset(mixed $var [, mixed $var [, $… ]])说明:$var是要销毁的变量,可以销毁一个或多个变量。要一次销毁所有的会话变量,使用session_unset();。5)销毁会话。使用完一个会话后,要注销对应的会话变量,然后再调用session_destroy()函数销毁会话,语法格式如下:bool session_destroy ( void )该函数将删除会话的所有数据并清除SessionID,关闭该会话。最近是换工作潮自己刻意“汇总整理了11篇带解析的PHP面试题的文档”,已上传百度云,关注公众号:“琉忆编程库”,回复:“php”,下载链接我发给你。二、cookieCookie可以用来存储用户名、密码、访问该站点的次数等信息。在访问某个网站时,Cookie将html网页发送到浏览器中的小段信息以脚本的形式保存在客户端的计算机上。一般来说,Cookie通过HTTP Headers从服务器端返回浏览器。首先,服务器端在响应中利用Set Cookie Header来创建一个Cookie。然后浏览器在请求中通过Cookie Header包含这个已经创建的Cookie,并且将它返回至服务器,从而完成浏览器的验证。Cookie技术有很多局限性,例如:1)多人共用一台计算机,Cookie数据容易泄露。2)一个站点存储的Cookie信息有限。3)有些浏览器不支持Cookie。4)用户可以通过设置浏览器选项来禁用Cookie。正是由于以上Cookie的一些局限性,所以,在进行会话管理时,SessionID通常会选择Cookie和URL两种方式来保存,而不是只保存在Cookie中。具体而言,Cookie的使用步骤如下:1)创建Cookie。在PHP中创建Cookie使用setcookie()函数,语法格式如下:bool setcookie(string $name [, string $value [, int $expire [, string $path [, string $domain [, bool $secure [, bool $httponly ]]]]]])① $name:表示Cookie的名字。② $value:表示Cookie的值,该值保存在客户端,所以不要保存比较敏感的数据。③ $expire:表示Cookie过期的时间,这是一个UNIX时间戳,即从UNIX纪元开始的秒数。对于$expire的设置一般通过当前时间戳加上相应的秒数来决定。例如,time()+1200表示Cookie将在20min后失效。如果不设置则Cookie将在浏览器关闭之后失效。④ $path:表示Cookie在服务器上的有效路径。默认值为设定Cookie的当前目录。⑤ $domain:表示Cookie在服务器上的有效域名。例如,要使Cookie能在example.com域名下的所有子域都有效,该参数应设为".example.com"。2)访问Cookie。通过setcookie()函数创建的Cookie是作为数组的单元,存放在预定义变量$_COOKIE中。也就是说,直接对$_COOKIE数组单元进行赋值也可以创建Cookie。但$_COOKIE数组创建的Cookie在会话结束后就会失效。3)删除Cookie。Cookie在创建时指定了一个过期时间,如果到了过期时间,那么Cookie将自动被删除。在PHP中没有专门删除Cookie的函数。如果为了安全方面的考虑,在Cookie过期之前就想删除Cookie,那么可以使用setcookie()函数或$_COOKIE数组将已知Cookie的值设为空。示例代码如下:<?php $_COOKIE[“user”]=“administrator”; setcookie(“password”,“123456”,time()+3600); $_COOKIE[“user”]=""; //使用$_COOKIE清除Cookie setcookie(“password”,""); //使用setcookie()函数清除Cookie print_r($_COOKIE); //输出:Array ( [user] => )?>Cookie和Session都是用来实现会话机制的,由于HTTP协议是无状态的,所以要想跟踪一个用户在同一个网站之间不同页面的状态,需要有一个机制,称为会话机制。预告:本周三更新PHP面试常考之网络协议,敬请期待。以上内容摘自《PHP程序员面试笔试宝典》书籍,该书已在天猫、京东、当当等电商平台销售。更多PHP相关的面试知识、考题可以关注公众号获取:琉忆编程库对本文有什么问题或建议都可以进行留言,我将不断完善追求极致,感谢你们的支持。

February 25, 2019 · 1 min · jiezi

219. 单页应用 会话管理(session、cookie、jwt)

原文链接:https://github.com/ly525/blog…关键字:http-only, cookie,sessionid, vue-router, react-router, 安全,localStorage, jwt需求描述内部管理平台,需要用户登录之后才能访问。现在将 该平台地址(www.xxx.com/home) 直接发给新来的运营同学前端需要检测该用户是否已登录,如果未登录,则将其 redirect 到登录页面因为该页面为单页应用,路由跳转不涉及后端的 302 跳转,使用前端路由跳转实现思路实现代码// 以 vue-router 为例// 登录中间验证,页面需要登录而没有登录的情况直接跳转登录router.beforeEach((to, from, next) => { const hasToken = document.cookie.includes(‘sessionid’); // 如果采用 jwt,则同样 hasToken = localStorage.jwt const pathNeedAuth = to.matched.some(record => record.meta.requiresAuth); // 用户本地没有后端返回的 cookie 数据 && 前往的页面需要权限 // if (pathNeedAuth && !hasToken ) { next({ path: ‘/login’, query: { redirect: to.fullPath }, }); } else if (hasToken && to.name === ’login’) { // 已登录 && 前往登录页面, 则不被允许,会重定向到首页 next({ path: ‘/’, }); } else { next(); }});应该在进入任何页面之前,判断:该页面是否需要权限才能访问:登录、注册页面不需要权限用户是否已经登录:本地 cookie (或者 localStorage)包含 session 相关信息 Cookie: csrftoken=YaHb…; sessionid=v40ld3x….如果 A页面需要权限 且 本地 cookie中包含了 sessionid 字段,则允许访问A页面,否则跳转到登录页面备注:sessionid 该字段由用户在登录之后,由后端框架通过 response.setCookie 写入前端 ,因此该字段需要和后端同学确认需要后端同学在 response header 中配置cookie中该字段的 http-only属性,允许前端读取 cookie。否则前端通过 document.cookie 读取到的 cookie 将不包含 sessionid 字段这个时候,可能会存在 js 读取cookie 导致不安全的情况,后端同学可以把 cookie 中的某个字段设置为 允许读取,其他 cookie 设置不允许读取,这样即使被第三方不安全脚本获取,也无法产生负面影响。如果用户已登录 && 在浏览器中输入了登录页地址,则将其重定向到首页更多说明这样做,前端就不必再向后端发起 API 做权限鉴定了(后端返回401,前端跳转到 401),减少不必要的API 请求,特别是如果在API响应时间过长的情况下,体验不太友好。用户修改 cookie,伪造 sessionid这样的话,前端就无能为力了,前端鉴权此时认为该用户合法。此时访问首页,将会调用获取数据的API。浏览器会将 用户伪造的 sessionid 带给后端,这时候就需要后端对 sessionid 进行较验了。比如校验前端带来的 sessionid 与数据库中的 sessionid 是否一致用户伪造的数据 sessionid 和 后端数据库中 sessionid 的概率 非常非常低,可以忽略不计,因为 sessionid 的位数一般在 32 位以上,因为里面包含了字母和数字,也就由 32 ^ 36 种可能结论:伪造没有意义,即使用户可以看到页面的样子,但是看不到数据采用 localStorage 而不是 sessionStorage 的原因(SessionStorage 失效场景)原因:sessionStorage 无法跨 Tab 共享用户在新打开一个 Tab,输入已经登录之后的某个页面通过target="_blank" 来打开新页面的时候,会导致会话失效在当前页面执行 Duplicate (复制 Tab),sessionStorage 失效 ...

February 20, 2019 · 1 min · jiezi

都9102年了,还问Session和Cookie的区别

1 前言最近看了一些同学的面经,发现无论什么技术岗位,还是会问到 Session 和 Cookie 的区别。所有学技术的同学都知道 Session 和 Cookie 函数怎么用,知道 Session 和 Cookie 的区别就是 Session 是储存在服务端的,Cookie 是存储在浏览器的。但是实际上是什么东西,一些刚学习技术的同学估计还是模糊,我刚学 PHP 的时候,这种感觉特别明显。PHP 中 Session 和 Cookie 的操作只要操作 $_COOKIE 和 $_SESSION 数组就可以了,而且操作方式和功能一模一样,搞得我一脸懵逼。最后,还是自己实现了一个 Session 操作类才恍然大悟,实质上就是两个不同的存储对象嘛。2 CookieCookie 的诞生是为了能让无状态的 HTTP 报文带上一些特殊的数据,让服务端能够辨识请求的身份。对于 Cookie 的概念就不多说了,Cookie 说简单点就是浏览器上的一个 key-value 存储对象,通过开发者工具直接看到 Cookie 的内容(F12)写入数据方式Cookie 写入数据的方式是通过 HTTP 返回报文 Header 部分 Set-Cookie 字段来设置,一个带有写 Cookie 指令的的 HTTP 返回报文如下HTTP/1.1 200 OKSet-Cookie: SESSIONID=e13179a6-2378-11e9-ac30-fa163eeeaea1; Path=/Transfer-Encoding: chunkedDate: Tue, 29 Jan 2019 07:12:09 GMTServer: localhost上述报文 Set-Cookie 指示浏览器设置 key 为 SESSIONID,value 为 e13179a6-2378-11e9-ac30-fa163eeeaea1 的 Cookie获取数据方式浏览器在发送请求的时候会检查当前域已经设置的 Cookie,在 HTTP 请求报文 Header 部分的 Cookie 字段里面带上 Cookie 的信息。下面捉取了一段 HTTP 报文GET http://10.0.1.24:23333/ HTTP/1.1Host: 10.0.1.24:23333Connection: keep-alivePragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Cookie: SESSIONID=e13179a6-2378-11e9-ac30-fa163eeeaea1从最后的 Cookie 字段看到,浏览器请求时带上了 key 为 SESSIONID,value 为 e13179a6-2378-11e9-ac30-fa163eeeaea1 的数据,后端直接解析 HTTP 报文就能获取 Cookie 的内容。3 SessionSession 在代码里面的语意是记录客户端状态的一个存储对象,是同一个客户端请求共享的数组。这个存储对象可以是文件、缓存系统、数据库。现在假设要使用 redis 来实现 Session 功能,那么就要求浏览器每次请求都要带一个相同的字符串作为身份信息,对应 redis 的 key,redis value 则为 Session 数组序列化的内容。那么如何让浏览器每次请求都带一个身份信息呢,这就是 Session 和 Cookie 的关系,通过 Cookie 传递这个身份信息。流程如下客户端请求服务端检查 Header,发现没有 Cookie,于是生成一个 UUID服务端处理数据,把部分数据(登录信息)存储到 redis 里面,UUID 为 key,用户 id 为 value返回报文中,增加 Set-Cookie 字段,内容带上 UUID浏览器收到报文,把 UUID 写进浏览器存储里面浏览器再次请求,带上当前的域的 Cookie,就是这个 UUID服务端通过 Cookie 字段获取到该 UUID,去 redis 里面获取用户的信息…4 手动实现 Session既然知道了 Session 的原理,我们手动实现一个 Session 操作类,采用文件保存的方式。http 框架采用 web.py,安装方式如下pip install web.pySession类我们要实现的这个类就叫 Sessionclass Session: def init(self): self.session_id = None # session 数组 self._items = dict() self._load()我们所有 session 文件放在 sessions 目录下,文件名为对应的 session id,内容为 Session 数组序列化的字符串。在初始化对象的时候通过获取名为 SESSIONID 的 Cookie,如果没有就生成一个新的。def _load(self): SESSIONID = web.cookies().get(‘SESSIONID’, None) if not SESSIONID: SESSIONID = uuid.uuid() self.session_id = SESSIONID self._loadFromDisk()获取到 SESSIONID 后,检查 sessions 目录下有没有对应的文件,如果有就读取并反序列化def _loadFromDisk(self): """ 从文件加载 SESSION """ file = ‘./sessions/%s’ % self.session_id if os.path.exists(file): f = open(file, ‘rb’) self._items = pickle.load(f) f.close()获取 Session 部分完成了,接下来就是保存 Session,我们要把 SESSIONID 写进 Cookie 里面,这样才能在下次请求时获取到对应的 SESSIONIDdef _setSessionCookie(self): """ Session id 写入 cookie """ web.setcookie(‘SESSIONID’, self.session_id)最后把 Session 的内容保存到文件里面def _saveToDisk(self): """ 保存 SESSION 到文件 """ f = open(’./sessions/%s’ % self.session_id, ‘wb’) pickle.dump(self._items, f) f.close()功能测试我们新建一个文件,叫 server.py,写入测试代码#!/usr/bin/env python# -- coding: utf-8 --# 测试 sessionimport webimport timefrom session import Sessionurls = ( ‘/’, ‘index’)app = web.application(urls, globals())class index: def GET(self): session = Session() if ’login_time’ not in session: session[’login_time’] = int(time.time()) return ’login time: %s’ % session[’login_time’]if name == “main”: app.run()在同一目录新建 session.py 文件,写入 Session 类代码#!/usr/bin/env python# -- coding: utf-8 --# Sessionimport osimport webimport uuidtry: import cPickle as pickleexcept ImportError: import pickleclass Session: __instance = None def new(cls): """ 单例模式 """ if cls.__instance is None: cls.__instance = object.new(cls) return cls.__instance else: return cls.__instance def init(self): self.session_id = None # session 数组 self._items = dict() self._load() def contains(self, key): return key in self._items def getitem(self, key): return self._items.get(key, None) def setitem(self, key, value): self._items[key] = value return True def delitem(self, key): if key in self._items: del self._items[key] return True def del(self): """ 析构函数,结束请求时执行 """ self._setSessionCookie() self._saveToDisk() def _load(self): SESSIONID = web.cookies().get(‘SESSIONID’, None) if not SESSIONID or SESSIONID is None: SESSIONID = uuid.uuid() self.session_id = SESSIONID self._loadFromDisk() def _loadFromDisk(self): """ 从文件加载 SESSION """ file = ‘./sessions/%s’ % self.session_id if os.path.exists(file): f = open(file, ‘rb’) self._items = pickle.load(f) f.close() def _setSessionCookie(self): """ Session id 写入 cookie """ web.setcookie(‘SESSIONID’, self.session_id) def _saveToDisk(self): """ 保存 SESSION 到文件 """ f = open(’./sessions/%s’ % self.session_id, ‘wb’) pickle.dump(self._items, f) f.close()再在同一目录新建 sessions 目录,存放我们的 Session 文件mkdir sessions启动服务[service@chengqm mysession]$ python server.py 23333http://0.0.0.0:23333/浏览器发起请求查看 Cookie 查看 Session 文件内容[service@chengqm mysession]$ cat sessions/e13179a6-2378-11e9-ac30-fa163eeeaea1(dp1S’login_time’p2I1548749002s.可以多次刷新和更换浏览器测试,测试结果是符合我们对 Session 的预期,简陋版 Session 类功能就算实现了。5 如果禁止 Cookie 是否可以获取 Session这是一道面试题,当年竟然能用这个问题问倒过一些朋友,还是有些意思的从前面可以知道,SESSIONID 是通过 Cookie 来传递,如果 Cookie 禁止了,还能获取 SESSIONID 吗? 答案是可以的既然 Cookie 禁止了,那么我们就可以用参数的方法传递 SESSIONID,后端返回的时候,增加一个返回参数,叫 SESSIONID,然后前端存储到 localstorage 里面前端请求的时候,去 localstorage 获取SESSIONID,在请求参数里面增加这一个参数后端 Session 处理,先尝试从 Cookie 中获取 SESSIONID,如果获取不到,再尝试从请求参数中获取 SESSIONID这样,就算禁止 Cookie 也是能获取 Session 的。6 总结最后,我们得出 Session 和 Cookie 区别和联系区别Cookie 是浏览器端的存储对象,有容量限制,通过 HTTP 报文与后端交互Session 是服务端的存储对象,实现的方式可以有文件系统、缓存系统、数据库联系Session 和 Cookie 都是为了实现 HTTP 请求带上客户端状态的方法Session 大多数情况下都是依赖 Cookie 来传递 Session Id ...

January 29, 2019 · 3 min · jiezi

利用 Postman Chrome app 和 Chrome 浏览器共享网站 cookie

背景作为一个Web工程师,最熟悉的日常工作莫过于后台接口开发与联调测试,而在接口测试上,大家最喜爱的工具清单里,必然少不了 Postman 这一利器。然而,有时接口测试需要准备好登录态,或者其他状态数据,而这些数据往往就存在浏览器 Cookie 里边。结合本文介绍的工具,便可以无缝在 Postman Chrome app (为什么强调是 Postman Chrome app,文章末尾会说明)和 Chrome 浏览器之间共享 Cookie,而这个共享过程对用户是透明的。工具清单以下工具请自行安装,我只贴下官方的软件界面截图。Chrome 浏览器Postman Chrome appPostman Interceptor使用步骤以下我们以 Github 网站为例,演示下如何实现 Cookie 共享。一、确认 Postman Interceptor 插件安装成功(如图所示)二、启动 Postman,在右上角的卫星小图标那里开启 Chrome Interceptor三、在 Chrome 浏览器里正常登陆 GitHub 网站(此步骤没什么好演示的 ╭(╯^╰)╮)四、在 Postman Chrome app 中直接模拟请求通知接口接口路径:https://github.com/notificati…也就是说,这个时候,我们虽然没有对 Postman 做特殊的 Cookie 设置,但是它的请求的登录态都被服务器验证通过了,cookie 共享成功!假如这个时候退出浏览器的登录态呢?我们先从 GitHub 退出登录,还是刚才的请求,这个时候的响应是:是的,因为 Chrome 里已经退出登录,所以 Postman 这边也自然失去登录态了,说明两边 Cookie 是同步的。Postman Interceptor 的 BonusPostman Interceptor 还有一点比较爽的是,它的 Request Capture 支持捕捉 Chrome 浏览器里的请求记录,并且自动同步到 Postman Chrome app 里边,这样的话,我们就可以方便直接在 Postman 里获取到我们需要测试的网络请求,而不是一个一个自己填写参数之类的了。缺陷遗憾的是,按照官方说明,现在 Postman Interceptor 的这个Cookie 共享还不能支持独立安装的桌面版(从官方下载而不是从 Chrome 应用市场下载)的 Postman Desktop,所以,如果你希望使用上述功能,你只能安装回 Postman Chrome app,而这个版本相对桌面版,功能自然也会少。Note: Interceptor feature is supported only in our Postman Chrome Apps and is not available in Postman Desktop Apps at the moment.另一方面,考虑到 Chrome 浏览器将会在不久的将来停掉 Chrome apps 的支持,可能这个方案也撑不了太久。如果你真心希望 Postman 将上述功能加到他们的桌面版里,可以到他们的官方GitHub issues去请愿,他们正在收集大家的意见。但是……这个请愿帖已经两年多了,而就在我表达请求之前的几个小时到几天之前,都有人陆续去请愿,所以也不知道会不会真的如愿了。总结对于确实需要获取网站 cookie 才能完成接口测试的场景,上述方法有一定的便利性,也才有必要使用我的方法,其他场景的接口测试,你们就无视我吧。参考链接Postman: Using the Interceptor to read and write cookiesPostman Help Center: How do I access Chrome’s cookies in Postman’s Chrome App?Postman Learning Center: Interceptor extensionGoogle is phasing out Chrome apps for Mac and Windows ...

January 14, 2019 · 1 min · jiezi

[译]使用Laravel访问前端Cookie

镜像地址: https://juejin.im/post/5c35c1…在我们的应用程序中,我们可以在JS端设置cookie,但我们也希望在后端使用。我们可以使用$_COOKIE 全局魔术变量,但如果我们使用Laravel,我们会使用它提供的方法。让我们下Laravel中是如何使用的在前端设置Cookie在这篇文章中,我们关注现有的cookie。如果对如何从 JavasScript 处理它们感兴趣,请阅读文档。现在,假设我们有一个带有“ is-collapsed ”键的现有cookie 。我们想检查后端的值,以便在服务器端执行某些操作。Laravel和Cookies我们可以通过 request()->cookie() 方法或使用 Cookie Facade 来访问我们的cookie 。问题是,如果我们想要访问我们在前端设置的 cookie,我们会得到 null。但是我们使用 $_COOKIE 变量,我们可以访问它,这证明 cookie 是存在的。那问题在什么地方呢?默认情况下,框架带有用于加密cookie的中间件。如果我们从后端设置一个cookie,它会自动加密,因此Laravel可以读取它。从JS我们没有任何加密,这就是我们无法从框架中访问它们的原因。如何解决这个问题?在 app/Http/Kernel.php 中, 在 web 中间件分组中(5.2+),我们可以找到 EncryptCookies::class 行。通过注释这个中间件,可以关闭 cookie 的自动加密,但这种方法不是我们想要的解决方案。建议的方法是使用中间件并添加一些不需要加密的排除项,Laravel无论怎样都应该访问它们。我们可以在 app/Http/Middlewares/EncryptCookies.php. 插入中间件的排除项。/** * The names of the cookies that should not be encrypted. * * @var array */protected $except = [ ‘is-collapsed’,];通过将 cookie 的名称添加到 except 数组,我们可以使用 Cookie Facade 或 request()->cookie() 方法读取cookie 。如果您对更多信息感兴趣,请查看 文档 或查看有关 加密如何工作 的章节。

January 9, 2019 · 1 min · jiezi

彻底弄懂session,cookie,token

session,cookie和token究竟是什么简述我在写之前看了很多篇session,cookie的文章,有的人说先有了cookie,后有了session。也有人说先有session,后有cookie。感觉都没有讲的很清楚,泛泛而谈。希望本篇文章对大家有所帮助注:本文需要读者有cookie,session,token的相关基础知识。http是一个无状态协议什么是无状态呢?就是说这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的。这种无状态的的好处是快速。坏处是假如我们想要把www.zhihu.com/login.html和www.zhihu.com/index.html关联起来,必须使用某些手段和工具cookie和session由于http的无状态性,为了使某个域名下的所有网页能够共享某些数据,session和cookie出现了。客户端访问服务器的流程如下首先,客户端会发送一个http请求到服务器端。服务器端接受客户端请求后,建立一个session,并发送一个http响应到客户端,这个响应头,其中就包含Set-Cookie头部。该头部包含了sessionId。Set-Cookie格式如下,具体请看Cookie详解Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]在客户端发起的第二次请求,假如服务器给了set-Cookie,浏览器会自动在请求头中添加cookie服务器接收请求,分解cookie,验证信息,核对成功后返回response给客户端注意cookie只是实现session的其中一种方案。虽然是最常用的,但并不是唯一的方法。禁用cookie后还有其他方法存储,比如放在url中现在大多都是Session + Cookie,但是只用session不用cookie,或是只用cookie,不用session在理论上都可以保持会话状态。可是实际中因为多种原因,一般不会单独使用用session只需要在客户端保存一个id,实际上大量数据都是保存在服务端。如果全部用cookie,数据量大的时候客户端是没有那么多空间的。如果只用cookie不用session,那么账户信息全部保存在客户端,一旦被劫持,全部信息都会泄露。并且客户端数据量变大,网络传输的数据量也会变大小结简而言之, session 有如用户信息档案表, 里面包含了用户的认证信息和登录状态等信息. 而 cookie 就是用户通行证tokentoken 也称作令牌,由uid+time+sign[+固定参数]token 的认证方式类似于临时的证书签名, 并且是一种服务端无状态的认证方式, 非常适合于 REST API 的场景. 所谓无状态就是服务端并不会保存身份认证相关的数据。组成uid: 用户唯一身份标识time: 当前时间的时间戳sign: 签名, 使用 hash/encrypt 压缩成定长的十六进制字符串,以防止第三方恶意拼接固定参数(可选): 将一些常用的固定参数加入到 token 中是为了避免重复查库存放token在客户端一般存放于localStorage,cookie,或sessionStorage中。在服务器一般存于数据库中token认证流程token 的认证流程与cookie很相似用户登录,成功后服务器返回Token给客户端。客户端收到数据后保存在客户端客户端再次访问服务器,将token放入headers中服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码token可以抵抗csrf,cookie+session不行假如用户正在登陆银行网页,该网页未对csrf攻击进行防护。攻击者就可以注入一张图片,该图片src为http://www.bank.com/api/transfer?count=1000&to=Tom。倘若是session+cookie,用户打开网页的时候就已经转给Tom1000元了。因为session一旦建立,当前域页面以及该页面路径以下所有页面都共享cookie。在img请求的瞬间,cookie会被浏览器自动添加到请求头中。但token不同,开发者在每次发起请求时手动将 Token 添加到请求中。即打开页面请求img时,该请求头中没有token分布式情况下的session和token我们已经知道session时有状态的,一般存于服务器内存或硬盘中,当服务器采用分布式或集群时,session就会面对负载均衡问题。负载均衡多服务器的情况,不好确认当前用户是否登录,因为多服务器不共享seesion。这个问题也可以将session存在一个服务器中来解决,但是就不能完全达到负载均衡的效果。当今的几种解决session负载均衡的方法。而token是无状态的,token字符串里就保存了所有的用户信息客户端登陆传递信息给服务端,服务端收到后把用户信息加密(token)传给客户端,客户端将token存放于localStroage等容器中。客户端每次访问都传递token,服务端解密token,就知道这个用户是谁了。通过cpu加解密,服务端就不需要存储session占用存储空间,就很好的解决负载均衡多服务器的问题了。这个方法叫做JWT(Json Web Token)总结session存储于服务器,可以理解为一个状态列表,拥有一个唯一识别符号sessionId,通常存放于cookie中。服务器收到cookie后解析出sessionId,再去session列表中查找,才能找到相应session。依赖cookiecookie类似一个令牌,装有sessionId,存储在客户端,浏览器通常会自动添加。token也类似一个令牌,无状态,用户信息都被加密到token中,服务器收到token后解密就可知道是哪个用户。需要开发者手动添加。jwt只是一个跨域认证的方案参考文章Cookie、Session、Token那点事儿cookie,token验证的区别有了cookie为什么需要sessionCSRF Token的设计是否有其必要性cookie,token,session三者的问题和解决方案负载均衡集群中的session解决方案JWT介绍Json Web Token 入门教程谢谢本文如有错误,欢迎留言讨论

January 9, 2019 · 1 min · jiezi

由一个需求(广告每天弹一次)引发……

需求:用户每天第一次打开网页时弹出一条广告,并且可以选择关闭(默认当天不再弹出)和近期不再弹出。如何从头开始实现?弹出框这里用alert代替了,可以用插件如https://v3.bootcss.com/javascript/#popovers、http://element-cn.eleme.io/#/zh-CN/component/dialog等实现。Cookie前端设置方法document.cookie = “date="+new Date(); // 创建一条cookie,浏览器关闭后就清理document.cookie = “user=mine;expires=” + new Date().setDate(time.getDate() + 7); // 再创建一条cookie,7天后会自动清理console.log(document.cookie); // user=mine; date=Thu Dec 20 2018 15:26:45 GMT+0800 (中国标准时间) /自行封装setCookie、getCookie、removeCookiefunction setCookie(name, value, expires){ document.cookie = ${name}=${value};expires=${expires};}function getCookie(name){ let cookies = document.cookie.split(”; “); let values = []; for(var i=0; i<cookies.length; i++){ values = cookies[i].split("=”); if(values[0] === name){ return values[1]; } } return null;}function removeCookie(name){ setCookie(name, “”, “-1”);}服务端设置方法Http无状态协议,只能在同一个网站(包括多个页面)下获取,存储在客户端本地的一段信息,帮助我们存储信息获取信息。但是同样有风险:我们自己在浏览器上可以操作或者设置Cookie。const express = require(’express’)const cookieParser = require(‘cookie-parser’)const app = express()app.use(cookieParser())app.get(’/’, (req,res)=>{ res.send(‘欢迎’ + req.cookies.username); // 如果有username cookie则显示username,否则显示undefined})app.get(’/login’, (req,res)=>{ let username = req.query.username; res.cookie(‘username’,username,{maxAge:99999, httpOnly:true}); // maxAge:cookie的有效期;httpOnly设置为true,可以防止XSS攻击,只能被web serve访问,不能通过document.cookie获取 res.send(‘登录成功’);})app.listen(80);至此,需求的思路就可以实现// 选择关闭(默认当天不再弹出)if(!getCookie(“isAlert”)){ alert(“我是弹出层”); let now = new Date(); setCookie(“isAlert”, “不要弹出了”, new Date(now.getFullYear(), now.getMonth(), now.getDate(), “23”, “59”, “59”));}// 选择近期(7天)不再弹出if(!getCookie(“isAlert”)){ alert(“我是弹出层”); let now = new Date(); setCookie(“isAlert”, “不要弹出了”, new Date(now.getFullYear(), now.getMonth(), now.getDate()+7, “23”, “59”, “59”));}cookie的学习同一网站共享一套cookie,它的数量和大小有限,有过期时间,JS中可以用document.cookie设置和访问。实现一个记住用户名(30天)和密码(7天)的需求// html code<form action="#" id=“form”> <input type=“text” id=“user”> <input type=“password” id=“psd”> <input type=“submit” value=“提交”> <input type=“button” id=“clear” value=“清除”></form>// js code// setCookie getCookie removeCookie 前面以封装var user = document.getElementById(“user”);var psd = document.getElementById(“psd”);var clear = document.getElementById(“clear”);form.onsubmit = function(){ var userTime = new Date(); userTime.setDate(userTime.getDate() + 30); var psdTime = new Date(); psdTime.setDate(psdTime.getDate() + 7); setCookie(“user”, user.value, userTime); setCookie(“psd”, psd.value, psdTime);} user.value = getCookie(‘user’); psd.value = getCookie(‘psd’);clear.onclick = function () { removeCookie(‘user’); removeCookie(“psd”); user.value = “”; psd.value = “”;};jquery-cookie https://cdn.bootcss.com/jquery-cookie/1.4.0/jquery.cookie.min.js获取:$.cookie(“name”),不存在就返回undefined,不管你看到的是什么,它都是字符串设置、修改:$.cookie(“name”, “value”) 有效期至当前会话关闭$.cookie(“name”, “value”, {expires: 7, path: “/”}) 有效期7天,有效路径是"/“删除:$.cookie(“name”, null); $.cookie(“name”, “”, {expires: -1})小技巧怎么获取当天最后一秒的时间戳let now = new Date();let resDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), “23”, “59”, “59”).getTime();怎么获取N天后的此时function N(N){ let now = new Date(); now.setDate(now.getDate() + N); return now;}怎么获取本周最后一秒let now = new Date();let day = now.getDay() || 7;/ 隐藏知识点:星期天返回的是0,typeof(now.getDay()) == “number” ,0 == false。 实质是这段代码 day = now.getDay() === 0 ? 7 : now.getDay();*/let weekLastDate = now.getDate()+(7-day); // 如果以周六为最后一天,这里就是用6减let resWeek = new Date(now.getFullYear(), now.getMonth(), weekLastDate, “23”, “59”, “59”);获取年和月的最后一秒就很简单了。 ...

December 25, 2018 · 2 min · jiezi

由一个需求(广告每天弹一次)引发……

需求:用户每天第一次打开网页时弹出一条广告,并且可以选择关闭(默认当天不再弹出)和近期不再弹出。如何从头开始实现?弹出框这里用alert代替了,可以用插件如https://v3.bootcss.com/javascript/#popovers、http://element-cn.eleme.io/#/zh-CN/component/dialog等实现。Cookie前端设置方法document.cookie = “date="+new Date(); // 创建一条cookie,浏览器关闭后就清理document.cookie = “user=mine;expires=” + new Date().setDate(time.getDate() + 7); // 再创建一条cookie,7天后会自动清理console.log(document.cookie); // user=mine; date=Thu Dec 20 2018 15:26:45 GMT+0800 (中国标准时间) /自行封装setCookie、getCookie、removeCookiefunction setCookie(name, value, expires){ document.cookie = ${name}=${value};expires=${expires};}function getCookie(name){ let cookies = document.cookie.split(”; “); let values = []; for(var i=0; i<cookies.length; i++){ values = cookies[i].split("=”); if(values[0] === name){ return values[1]; } } return null;}function removeCookie(name){ setCookie(name, “”, “-1”);}服务端设置方法Http无状态协议,只能在同一个网站(包括多个页面)下获取,存储在客户端本地的一段信息,帮助我们存储信息获取信息。但是同样有风险:我们自己在浏览器上可以操作或者设置Cookie。const express = require(’express’)const cookieParser = require(‘cookie-parser’)const app = express()app.use(cookieParser())app.get(’/’, (req,res)=>{ res.send(‘欢迎’ + req.cookies.username); // 如果有username cookie则显示username,否则显示undefined})app.get(’/login’, (req,res)=>{ let username = req.query.username; res.cookie(‘username’,username,{maxAge:99999, httpOnly:true}); // maxAge:cookie的有效期;httpOnly设置为true,可以防止XSS攻击,只能被web serve访问,不能通过document.cookie获取 res.send(‘登录成功’);})app.listen(80);至此,需求的思路就可以实现// 选择关闭(默认当天不再弹出)if(!getCookie(“isAlert”)){ alert(“我是弹出层”); let now = new Date(); setCookie(“isAlert”, “不要弹出了”, new Date(now.getFullYear(), now.getMonth(), now.getDate(), “23”, “59”, “59”));}// 选择近期(7天)不再弹出if(!getCookie(“isAlert”)){ alert(“我是弹出层”); let now = new Date(); setCookie(“isAlert”, “不要弹出了”, new Date(now.getFullYear(), now.getMonth(), now.getDate()+7, “23”, “59”, “59”));}cookie的学习同一网站共享一套cookie,它的数量和大小有限,有过期时间,JS中可以用document.cookie设置和访问。实现一个记住用户名(30天)和密码(7天)的需求// html code<form action="#" id=“form”> <input type=“text” id=“user”> <input type=“password” id=“psd”> <input type=“submit” value=“提交”> <input type=“button” id=“clear” value=“清除”></form>// js code// setCookie getCookie removeCookie 前面以封装var user = document.getElementById(“user”);var psd = document.getElementById(“psd”);var clear = document.getElementById(“clear”);form.onsubmit = function(){ var userTime = new Date(); userTime.setDate(userTime.getDate() + 30); var psdTime = new Date(); psdTime.setDate(psdTime.getDate() + 7); setCookie(“user”, user.value, userTime); setCookie(“psd”, psd.value, psdTime);} user.value = getCookie(‘user’); psd.value = getCookie(‘psd’);clear.onclick = function () { removeCookie(‘user’); removeCookie(“psd”); user.value = “”; psd.value = “”;};jquery-cookie https://cdn.bootcss.com/jquery-cookie/1.4.0/jquery.cookie.min.js获取:$.cookie(“name”),不存在就返回undefined,不管你看到的是什么,它都是字符串设置、修改:$.cookie(“name”, “value”) 有效期至当前会话关闭$.cookie(“name”, “value”, {expires: 7, path: “/”}) 有效期7天,有效路径是"/“删除:$.cookie(“name”, null); $.cookie(“name”, “”, {expires: -1})小技巧怎么获取当天最后一秒的时间戳let now = new Date();let resDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), “23”, “59”, “59”).getTime();怎么获取N天后的此时function N(N){ let now = new Date(); now.setDate(now.getDate() + N); return now;}怎么获取本周最后一秒let now = new Date();let day = now.getDay() || 7;/ 隐藏知识点:星期天返回的是0,typeof(now.getDay()) == “number” ,0 == false。 实质是这段代码 day = now.getDay() === 0 ? 7 : now.getDay();*/let weekLastDate = now.getDate()+(7-day); // 如果以周六为最后一天,这里就是用6减let resWeek = new Date(now.getFullYear(), now.getMonth(), weekLastDate, “23”, “59”, “59”);获取年和月的最后一秒就很简单了。 ...

December 23, 2018 · 2 min · jiezi

一文带你看懂cookie,面试前端不用愁

本文由云+社区发表在前端面试中,有一个必问的问题:请你谈谈cookie和localStorage有什么区别啊?localStorage是H5中的一种浏览器本地存储方式,而实际上,cookie本身并不是用来做服务器存储的。但在 localStorage 出现之前,cookie被滥用当做了存储工具,什么数据都放在cookie中,即使这些数据只在页面中使用、而不需要随请求传送到服务端(当然cookie也做了一些限制:大小受限、每个域名下生成的cookie数量受限)。就像CSS中的float,最初被设计出来的初衷,是用于做文字环绕效果的,就是一个图片、一段文字,给图片加上float:left的样式后,就会产生文字环绕图片的效果。但是后来发现float结合<div>,可以实现之前通过<table>实现的网页布局,因此就被“误用于”网页布局了。那么通过阅读本文,你可以了解:1.cookie是什么,cookie的属性有哪些,如何设置cookie,cookie的缺点,和session的区别2.不再混淆cookie和webStorage,简单介绍浏览器的本地存储的两种方式:sessionStorage和localStorage1.cookie1.1 cookie是什么cookie是当你浏览某个网站的时候,由web服务器存储在你的机器硬盘上的一个小的文本文件。它其中记录了你的用户名、密码、浏览的网页、停留的时间等等信息。当你再次来到这个网站时,web服务器会先看看有没有它上次留下来的cookie。如果有的话,会读取cookie中的内容,来判断使用者,并送出相应的网页内容,比如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等。当客户端要发送http请求时,浏览器会先检查下是否有对应的cookie。有的话,则自动地添加在request header中的cookie字段。注意,每一次的http请求时,如果有cookie,浏览器都会自动带上cookie发送给服务端。那么把什么数据放到cookie中就很重要了,因为很多数据并不是每次请求都需要发给服务端,毕竟会增加网络开销,浪费带宽。所以对于那设置“每次请求都要携带的信息(最典型的就是身份认证信息)”就特别适合放在cookie中,其他类型的数据就不适合了。简单的说就是:(1) cookie是以小的文本文件形式(即纯文本),完全存在于客户端;cookie保存了登录的凭证,有了它,只需要在下次请求时带着cookie发送,就不必再重新输入用户名、密码等重新登录了。(2) 是设计用来在服务端和客户端进行信息传递的;这里我简单地画了个图,可以方便理解:第一次请求时:第一次请求下一次请求时:下一次请求浏览器会把cookie放到请求头一起提交给服务器,cookie携带了会话ID信息。服务器会根据cookie辨认用户:由于cookie带了会话的ID信息,可以通过cookie找到对应会话,通过判断会话来判断用户状态。1.2 cookie的属性在浏览器的控制台中,可以直接输入:document.cookie来查看cookie。cookie是一个由键值对构成的字符串,每个键值对之间是“; ”即一个分号和一个空格隔开。document.cookie注意,这个方法只能获取非 HttpOnly 类型的cookie每个cookie都有一定的属性,如什么时候失效,要发送到哪个域名,哪个路径等等。这些属性是通过cookie选项来设置的,cookie选项包括:expires、domain、path、secure、HttpOnly。在设置任一个cookie时都可以设置相关的这些属性,当然也可以不设置,这时会使用这些属性的默认值。在设置这些属性时,属性之间由一个分号和一个空格隔开。代码示例如下:“key=name; expires=Sat, 08 Sep 2018 02:26:00 GMT; domain=ppsc.sankuai.com; path=/; secure; HttpOnly"cookie的属性可以在控制台查看:Application选项,左边选择Storage,最后一个就是cookie,点开即可查看。Expires、Max Age:Expires选项用来设置“cookie 什么时间内有效”。Expires其实是cookie失效日期,Expires必须是 GMT 格式的时间(可以通过 new Date().toGMTString()或者 new Date().toUTCString() 来获得)。new Date().toGMTString()或者 new Date().toUTCString()如expires=Sat, 08 Sep 2018 02:26:00 GMT表示cookie将在2018年9月8日2:26分之后失效。对于失效的cookie浏览器会清空。如果没有设置该选项,这样的cookie称为会话cookie。它存在内存中,当会话结束,也就是浏览器关闭时,cookie消失。补充:Expires是 http/1.0协议中的选项,在http/1.1协议中Expires已经由 Max age 选项代替,两者的作用都是限制cookie 的有效时间。Expires的值是一个时间点(cookie失效时刻= Expires),而Max age的值是一个以秒为单位时间段(cookie失效时刻= 创建时刻+ Max age)。 另外, Max age的默认值是 -1(即有效期为 session ); Max age有三种可能值:负数、0、正数。负数:有效期session;0:删除cookie;正数:有效期为创建时刻+ Max ageDomain和PathDomain是域名,Path是路径,两者加起来就构成了 URL,Domain和Path一起来限制 cookie 能被哪些 URL 访问。即请求的URL是Domain或其子域、且URL的路径是Path或子路径,则都可以访问该cookie,例如:某cookie的 Domain为“baidu.com”, Path为“/ ”,若请求的URL(URL 可以是js/html/img/css资源请求,但不包括 XHR 请求)的域名是“baidu.com”或其子域如“api.baidu.com”、“dev.api.baidu.com”,且 URL 的路径是“/ ”或子路径“/home”、“/home/login”,则都可以访问该cookie。补充:发生跨域xhr请求时,即使请求URL的域名和路径都满足 cookie 的 Domain和Path,默认情况下cookie也不会自动被添加到请求头部中。SizeCookie的大小SecureSecure选项用来设置cookie只在确保安全的请求中才会发送。当请求是HTTPS或者其他安全协议时,包含 Secure选项的 cookie 才能被发送至服务器。默认情况下,cookie不会带Secure选项(即为空)。所以默认情况下,不管是HTTPS协议还是HTTP协议的请求,cookie 都会被发送至服务端。但要注意一点,Secure选项只是限定了在安全情况下才可以传输给服务端,但并不代表你不能看到这个 cookie。补充:如果想在客户端即网页中通过 js 去设置Secure类型的 cookie,必须保证网页是https协议的。在http协议的网页中是无法设置secure类型cookie的。httpOnly这个选项用来设置cookie是否能通过 js 去访问。默认情况下,cookie不会带httpOnly选项(即为空),所以默认情况下,客户端是可以通过js代码去访问(包括读取、修改、删除等)这个cookie的。当cookie带httpOnly选项时,客户端则无法通过js代码去访问(包括读取、修改、删除等)这个cookie。在客户端是不能通过js代码去设置一个httpOnly类型的cookie的,这种类型的cookie只能通过服务端来设置。可以在浏览器的控制台中看出哪些cookie是httpOnly类型的,HTTP下带绿色对勾的即是,如图:httponly只要是httponly类型的,在控制台通过document.cookie是获取不到的,也不能进行修改。之所以限制客户端去访问cookie,主要还是出于安全的目的。因为如果任何 cookie 都能被客户端通过document.cookie获取,那么假如合法用户的网页受到了XSS攻击,有一段恶意的script脚本插到了网页中,这个script脚本,通过document.cookie读取了用户身份验证相关的 cookie,那么只要原样转发cookie,就可以达到目的了。1.3 cookie的设置、读取、删除方法cookie既可以由服务端来设置,也可以由客户端来设置。1.3.1 服务端设置cookie前面1.1中介绍过,客户端第一次向服务端请求时,在相应的请求头中就有set-cookie字段,用来标识是哪个用户。下图我是登录腾讯云的某个页面的响应头截图,可以看到响应头中有两个set-cookie字段,每段对应一个cookie,注意每个cookie放一个set-cookie字段中,不能将多个cookie放在一个set-cookie字段中。具体每个cookie设置了相关的属性:expires、path、httponly,具体属性含义可以结合1.2 cookie的属性来看:response headers服务端设置cookie的范围:服务端可以设置cookie 的所有选项:expires、domain、path、secure、HttpOnly1.3.2 客户端设置cookiecookie不像web Storage有setItem,getItem,removeItem,clear等方法,需要自己封装。简单地在浏览器的控制台里输入:document.cookie=“name=lynnshen; age=18"但发现只添加了第一个cookie:“name=lynnshen”,后面的cookie并没有添加进来:最简单的设置多个cookie的方法就是重复执行document.cookie = “key=name”:document.cookie = “name=lynnshen”;document.cookie = “age=18”;再看控制台:注意:当name、domain、path 这3个字段都相同的时候,cookie会被覆盖。下面是我自己简单封装的设置、读取、删除cookie的方法:设置cookie:function setCookie(name,value,iDay){ var oDate = new Date(); oDate.setDate(oDate.getDate() + iDay); document.cookie = name + “=” + value + “;expires=” + oDate;}读取cookie,该方法简单地认为cookie中只有一个“=”,即key=value,如有更多需求可以在此基础上完善:function getCookie(name){ //例如cookie是"username=abc; password=123” var arr = document.cookie.split(’; ‘);//用“;”和空格来划分cookie for(var i = 0 ;i < arr.length ; i++){ var arr2 = arr[i].split("=”); if(arr2[0] == name){ return arr2[1]; } } return “”;//整个遍历完没找到,就返回空值}删除cookie:function removeCookie(name){ setCookie(name, “1”, -1)//第二个value值随便设个值,第三个值设为-1表示:昨天就过期了,赶紧删除}1.4 cookie的缺点cookie的缺点:(1) 每个特定域名下的cookie数量有限:IE6或IE6-(IE6以下版本):最多20个cookieIE7或IE7+(IE7以上版本):最多50个cookieFF:最多50个cookieOpera:最多30个cookieChrome和safari没有硬性限制当超过单个域名限制之后,再设置cookie,浏览器就会清除以前设置的cookie。IE和Opera会清理近期最少使用的cookie,FF会随机清理cookie;(2) 存储量太小,只有4KB;(3) 每次HTTP请求都会发送到服务端,影响获取资源的效率;(4) 需要自己封装获取、设置、删除cookie的方法;1.5 cookie和session的区别cookie是存在客户端浏览器上,session会话存在服务器上。会话对象用来存储特定用户会话所需的属性及配置信息。当用户请求来自应用程序的web页时,如果该用户还没有会话,则服务器将自动创建一个会话对象。当会话过期或被放弃后,服务器将终止该会话。cookie和会话需要配合,具体内容参见1.1节。当cookie失效、session过期时,就需要重新登录了。2.浏览器本地存储:2.1 localStorage和sessionStorage在较高版本的浏览器中,js提供了两种存储方式:sessionStorage和globalStorage。在H5中,用localStorage取代了globalStorage。sessionStorage用于本地存储一个会话中的数据,这些数据只有在同一个会话中的页面才能访问,并且当会话结束后,数据也随之销毁。所以sessionStorage仅仅是会话级别的存储,而不是一种持久化的本地存储。localStorage是持久化的本地存储,除非是通过js删除,或者清除浏览器缓存,否则数据是永远不会过期的。浏览器的支持情况:IE7及以下版本不支持web storage,其他都支持。不过在IE5、IE6、IE7中有个userData,其实也是用于本地存储。这个持久化数据放在缓存中,只有不清理缓存,就会一直存在。2.2 web storage和cookie的区别(1) web storages和cookie的作用不同,web storage是用于本地大容量存储数据(web storage的存储量大到5MB);而cookie是用于客户端和服务端间的信息传递;(2) web storage有setItem、getItem、removeItem、clear等方法,cookie需要我们自己来封装setCookie、getCookie、removeCookie,具体可见1.3节;3.小结本文纵向上深度介绍了cookie相关的知识,包括cookie的作用、各个属性的用途、cookie的设置、缺点等等。横向上,将cookie和会话、localStorage做了比较。如有问题,欢迎指正。此文已由作者授权腾讯云+社区发布搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包! ...

December 11, 2018 · 1 min · jiezi

老旧话题:重新看看当年感觉很难的session

原文地址:https://t.ti-node.com/thread/…这基本上算是个老旧的话题了,几乎所有phper在第一次面试的时候都会被问到关于session的问题,如果不出意外,往往是如下三板斧:php的session是什么东西php的session存在什么地方、时候过期php的session和cookie有什么区别这三个问题堪称是关于php session三大基础问题了,要是掌握不好,直接导致面试挂掉,令人唏嘘不已。就以上三个问题简单回顾一下:session翻译成中文,大抵就是会话。我们知道http协议是一个无状态的协议,用极为粗暴的土话表示无状态就是说“你压根不知道这个http请求是哪个犊子发起的”或者“你永远不知道这个http请求的那头到底是上次那个哈士奇还是上上次那个胖子”,所以为了解决这个问题,php引入session来额外标记“到底谁发起的这个http请求”。在php中,php会为每个不同的用户生成一个随机的session id,每个人拥有的session id都是不同的。用户在与服务器产生的每一次交互中,都是利用session id来辨别的用户。让php产生session是一件很容易的事情,直接调用session_start()函数就可以了,如下图就是产生的session文件:其中sess是文件前缀,后面的“njjf8l3lh**ff6”就是你的session id了。但是现在session文件内容是空的,如果我们用如下代码,就可以产生session文件的内容:<?php// 开启sessionsession_start();$_SESSION[‘hello’] = ‘world’;刷新一下网页,然后在再次查看原来的session文件,其中就会有如下内容:就是说,你往全局变量$_SESSION保存的内容本质上都是PHP用文本形式给你存储到服务器上了。服务器根据你的session id读取相应的session文件然后把其中内容读出来,你就会得到你的$_SESSION数据。php的session默认是以文件的形式存储的系统磁盘中,在运行于ubuntu 16.04系统的php 7.0.28中,session是存储于/var/lib/php/sessions文件夹下,可以通过php.ini配置文件中的session.save_path来查看确定。php的过期时间是由php配置项session.gc_maxlifetime来确定的,值的单位是秒钟,默认是1440,也就是说当这个session文件具体上次修改时间超过了1440秒后这个session文件就算是过期了。值得注意的是,过期了不代表这个session文件会马上被垃圾回收机制删除掉,还是有可能会残存一段时间的。那么,究竟何时会被删除?这取决于session.gc_probability和session.gc_divisor两个配置项了。这两个选项的比值 ( session.gc_probability / session.gc_divisor ) 就是触发垃圾回收机制的概率,比如 ( 1 / 100 ) 就可以简单粗暴的理解为“每产生100个请求,就有1次会触发php垃圾回收机制去删除过期的session文件”,所以你记住了:在php中如果你想要一个精确过期的session文件,最起码默认的session配置是绝对不可能的。话说回来,还不都是因为php并没有启动一个单独的线程或者进程去扫描垃圾,所以,也只能用这个“概率”这种粗暴的方式来解决这个问题,又不是不能用。开篇说了,为了搞明白“到底是哈士奇还是胖子”的问题,不得不引入额外标记数据才行,所以实际上,先有的cookie而有后的session,都是为了解决这个问题而产生的。二者的恩怨情仇在于:cookie存在于客户端,而session存在于服务器端,所以session相对更安全服务器可以读取session和cookie,但是客户端(也就是浏览器)只能读取cookie默认情况下,session是离不开cookie的,说到底“安全的session使用方式”必须依靠cookie才能混口饭吃。因为session id就是依靠cookie保存起来的,客户端浏览器每次发送请求都会携带上该cookie,该cookie默认名称是PHPSESSID,数值就是session id。如果说就是用不了cookie,那么session也并不是真的不能用。禁用cookie的情况下,session可以通过配置利用URL来传递,也就是query string直接暴露在网址中,非常不安全非常吓人,严重不推荐这种方式,甚至应该直接禁用!cookie大小稍微有限制(据说考虑用localstorage代替?),session相对宽松大概就这些,不再赘述,我是建议大家配合php.ini文件去研究上面三个问题。如果说真的只回顾一下这三个问题,那岂不是真的应了“一看标题猛如虎,打开内容1-5”?我说过了的,我这里是个正经的博客网站,是个真正的有些内涵的php文化网站,不能只讲些个初级的内容,是个话题都都要无论如何强塞点儿看起来高端的玩意进去撑场面。刚叨叨过了,默认配置下session是以文本文件形保存在服务器的某个文件夹中的,有心的人应该知道“一个目录中文件过多是会降低读取效率的”,所以,在用一些PC软件的时候可以看到这些软件会把TA需要的数据分散开来到不同的次级目录中去。php的session文件也可以这么干,总体来说是比较简单粗暴的。我们需要关注下两个php配置项:一个是session.save_handler,默认这货的值是“files”,也就是文件一个是session.save_path,默认这货的值是一个目录路径,比如/var/lib/php/session。现在我们将这个值改成类似于session.save_path = “N;/path"这样的,其中N是一个正整数,这个数值的含义就是指将目录分成几个层次,比如我们修改成session.save_path = “2;/var/lib/php/sessions”,然后重启一下apache或者fpm进程管理器,然后执行如下代码:<?phpecho “let rock session”;session_start();刷新网页,如下图所示:错误原因相比大家看到了,大概意思就是说“/var/lib/php/sessions/n/j/”这个文件夹不存在,那么切换到这个目录下看看,如下图:果然是空的,也就说没有/n/j这个子目录,看来得手工创建了。然而,真的不能去手工创建,因为你哪儿知道文件夹的名字是啥?回到配置文件一顿研究,在session.save_path配置项附近发现如下英文字样:; NOTE 1: PHP will not create this directory structure automatically.; You can use the script in the ext/session dir for that purpose.; NOTE 2: See the section on garbage collection below if you choose to; use subdirectories for session storage英文比较蹩脚昂,大概翻译一下,多包涵:; NOTE 1: PHP压根不会帮你创建这些文件夹,您自己个儿下载php源码包,到ext目录的session目中去找那个脚本去创建; NOTE 2: 如果你要用子目录存储session的话,记得看下垃圾回收,不看就有坑。(坑在这里直接告诉大家吧,大概就是说你要自己搞子目录存session,那我那个靠信仰和概率才能触发的垃圾回收机制就压根就不触发了,你自己想办法搞定你的过期session,我不管了)所以呢,我们下载一个php源码包,最好是和你运行环境版本一样的php源码包并解压,命令行切到ext/session目录下,如下图:看到那个mod_files.sh没?Linux下就这脚本。mod_files.bat就是给windows用的。给这个脚本chmod +x mod_files.sh加个执行权限,然后查看下使用方式:为了帮助眼近视的读者,友情翻译一下使用方式:./mod_files.sh ‘session文件根目录’ 目录深度 哈希函数比特量对应我的php开发环境就是:./mod_files.sh /var/lib/php/sessions/ 2 5其中第一项就是你存储session的根目录,第二项就是那个N,第三项查看session.hash_bits_per_character配置项然后执行,如下图所示:此时到/var/lib/php/sessions中查看下,果然有目录了,那么,再次刷新网页,本以为很顺利的你可能依然会遇到错误,如下:session_start(): open(/var/lib/php/sessions/n/j/sess_njjf8l3lhfrpq8nrlnl1d9qff6, O_RDWR) failed: Permission denied (13)模模糊糊认得Permission denied这几个字母,好像是权限的问题,难道是因为当前apache进程用户或者fpm进程用户没有权限往这些目录写数据吗?改下这些目录的拥有者撒,改成www-data(我系统中fpm的运行用户),再试试,果然好了!总有刁民以为这就可以解决很大的问题了,然而很悲剧的是:并不是。当前这个方案一定程度可以解决session文件过多的问题,但是依然有两个问题没有得到解决:依然是文件存储,如果访问量太大的话,session文件从硬盘的读取IO或许会成为程序的瓶颈,当然SSD速度一定会好很多如果网站分别部署到了两台服务器上,session无法共享,出现故障。什么意思呢?就是为了保证高可用,网站程序分别在A服务器上和B服务器上,然后最外面使用一台nginx挡在最前面做负载均衡,路人甲的某次http请求可能会被分配到A上,也可能会被分配到B上。路人甲在A上产生的session文件会被保存到A服务器硬盘上,但是服务器B上却没有,如果该用户请求被打到B上的时候,很不幸,session丢失了,一些数据也就会丢失,路人甲八成会骂娘骂客服。也就说,A服务器和B服务器需要共享同一套session!借此,就引入一个问题,就是分布式web部署中,如何解决session共享的问题!关子我就不卖了,没意思,首先想到的是redis,为A和B提供一台C redis服务器就可以了,这样可以“ 多快好省 ”地一举解决问题!按照预想,引入redis后可以顺利解决三个问题:内存级的读写速度,唰唰唰!session轻松easy实现了共享,哪怕以后业务服务器继续横向扩展到服务器Dsession的过期终于可以精确到秒了,说没就没,不用再靠信仰和概率了将session存入redis需要修正如下两处php配置,首先设置session.save_handler = redis,其次是设置ession.save_path = “tcp://127.0.0.1:6379”,然后重启apache或者fpm,刷新一下网页,如果网页不报什么错误,理论上session数据就已经到redis中去了,连接redis查看下key,如下图:从上至下我一共执行了五次redis命令,分别表示:查看所有keys从而获取php分配给我的session文件名称获取这个key的剩余时间,过期后redis该key算失效了查看这个key的数据类型,可以看出是string类型使用get直接获取string的值过了一段时间,我又刷新了一下网页,然后再次用ttl看该key的剩余时间,再次被延长到1440秒了除了redis外(memcache我就不举例了,和redis类似),还有一种方案就是通过nfs共享来实现,大概原理就是弄一台服务器,通过内网共享对所有php业务服务器开放读写,大家知道linux下磁盘是可以挂载在某个文件夹下的,所以将nfs挂载到各个php业务服务器的某个目录下,然后按照上述文章修改响应配置就可以了。这个,我也没有尝试过也懒得自己去尝试了,所以偷个懒直接给大家抛个连接吧,是老叶博客上的一篇文章,《iMySQL | 老叶茶馆,PHP实现多服务器session共享之NFS共享》。装逼完毕,如有问题,火速留言指正! ...

December 3, 2018 · 1 min · jiezi

LocalStorage、SessionStorage

window.sessionStorage和window.localStorage接口用于脚本在浏览器保存数据。LocalStorage基本使用设置window.sessionStorage.setItem(‘key’, ‘value’);window.localStorage.setItem(‘key’, ‘value’);获取window.sessionStorage.getItem(‘key’)window.localStorage.getItem(‘key’)清除localStorage.removeItem(‘key’);window.localStorage.clear()完整用法注意点localStorage是html5技术提供的API,html5中新增加的标签,技术(包括promise,localStorage等),统称为html5session是服务器上存的hash,但localStorage实质也是一个hash,只不过是浏览器上的hashlocalStorage只能存String类型的字符串存函数会转化成字符串。存对象的时候会变成"[object Object]",因为({1:‘xxx’}).toString()//"[object Object]“解决方法:用json来存。例如:localStorage.setItem(‘jsonString’, JSON.stringify({name: ‘mtt’}))使用注意localStorage里的数据和js变量有什么区别?当一个js变量被从新赋值,变量的值当即被改变,但当页面刷新时,变量又回到最初的状态。而localStorage的变量不存在页面里,windows系统存在客户端本地的C盘的一个文件里。简单的使用实例想要只提示用户一次,当下次用户进入这个网站上的时候,不跳出提示框。<script> let already = localStrorage.getItem(‘已经提示了’) if(!already){ alert(‘你好,我们的网站即将改版了’) localStorage.setItrm(‘已经提示了’, true) }</script>总结LocalStorage 跟 HTTP 无关(而cookie是http的一个头)发送HTTP请求时 不会带上 LocalStorage 的值只有相同域名的页面才能互相读取 LocalStorage(没有同源那么严格)每个域名 localStorage 最大存储量为 5Mb 左右(每个浏览器不一样)常用场景:记录有没有提示过用户(没有用的信息,不能记录密码)LocalStorage 永久有效,除非用户主动清理缓存SessionStoragesessionStorage保存的数据用于浏览器的一次会话(session),当会话结束(通常是窗口关闭),数据被清空;localStorage保存的数据长期存在,下一次访问该网站的时候,网页可以直接读取以前保存的数据。除了保存期限的长短不同,这两个对象的其他方面都一致。总结:SessionStorage 在用户关闭页面(会话结束)后就失效。其余的和localstorage一样

October 16, 2018 · 1 min · jiezi

以登录注册理解Cookie的作用过程

这篇文章是前一篇文章(Cookie理论知识)的实践性理解完整代码:完整代码Cookie在注册登录时的作用过程:注册注册时把账号密码写入数据库登录第一次登录时服务器给浏览器发送Cookie.后台的登录路由代码(nodejs):else if (path === ‘/sign_in’ && method === ‘POST’) { readBody(request).then((body) => { let strings = body.split(’&’) // [’email=1’, ‘password=2’, ‘password_confirmation=3’] let hash = {} strings.forEach((string) => { // string == ’email=1’ let parts = string.split(’=’) // [’email’, ‘1’] let key = parts[0] let value = parts[1] hash[key] = decodeURIComponent(value) // hash[’email’] = ‘1’ }) let { email, password } = hash var users = fs.readFileSync(’./db/users’, ‘utf8’) try { users = JSON.parse(users) // [] } catch (exception) { users = [] } let found for (let i = 0; i < users.length; i++) { if (users[i].email === email && users[i].password === password) { found = true break } } if (found) {//关键在这里,验证成功,设置登录Cookie为登录的邮箱,并放在响应里发给浏览器 response.setHeader(‘Set-Cookie’, sign_in_email=${email}) response.statusCode = 200 } else { response.statusCode = 401 } response.end() }) }在登录成功的一瞬间,需要后台设置一个Cookie,记录一下登陆的用户id(这里用邮箱表示,代码在上面),然后发响应给浏览器例如在服务器端设置响应头:set-cookies:user_email=1@mtt.com这时候我们查看响应:发现响应头已经设置cookie.然后跳转到主页,这时候我们查看跳转到主页的请求:发现跳转到主页的请求头中包含cookie字段(以后访问这个域名都会带着这个Cookie)!所以,就像上篇文章说的:如果服务器给了浏览器一个setcookie的响应头,那么这个浏览器以后所有的请求,只要是相同的源(即就是上次给我发送Cookie的那个域名,域名和端口相同),那就么就会把当时服务器发给这个浏览器的Cookie带着以后,浏览器一旦访问这个路径,浏览器就会附上这段 Cookie 发送给服务器即:第一次请求,服务器为浏览器设置Cookie.下次请求,浏览器带上Cookie,发送给服务器.第一次登录的时候,服务器给浏览器的响应设置一个Cookie,set-cookies:user_email=1@mtt.com,然后当浏览器下次进行请求的时候,发现Cookie中有名为User_email的Cookie,而且我发送请求的域名还是上次发给我带Cookie的响应的那个域名.那么就无需再次登录了.相当于服务器给浏览器发了进入门票,下次或下下次浏览器在进入服务器的时候给服务器看票就可以了后台读取Cookie保留登录状态与删除Cookie退出登录状态首页代码:<body> <h1>我是首页</h1> <div class=""> <a href="./sign_up">注册</a> <a href="./sign_in">登录</a> </div> <h1>你的状态是:status</h1> <h1>你的邮箱账号是:email</h1> <h1>你的密码是:password</h1> <a href=“javascript:;” id=“logOffBtn”>退出登录(删除cookie)</a></body><script>logOffBtn.addEventListener(“click”, () => { // 删除一个现存 Cookie 的唯一方法,是设置它的expires属性为一个过去的日期。 document.cookie = ‘sign_in_email=;expires=Thu, 01-Jan-1970 00:00:01 GMT’ window.location = “/” })</script>后台路由代码if (path === ‘/’) { response.statusCode = 200 let string = fs.readFileSync(’./index.html’) string = string.toString(); var users = fs.readFileSync(’./db/users’, ‘utf8’) users = JSON.parse(users)//转化为user对象数组 console.log(users); let cookies = request.headers.cookie || ‘’//[’email=111’, ‘asdasd=111’] cookies = cookies.split("; “) let hash={} cookies.forEach((string)=>{ let parts = string.split("=”) let key = parts[0] let value = parts[1] hash[key] = value; }) let eamil = hash.sign_in_email let foundedUser users.forEach((userObj)=>{ if(userObj.email===eamil){ foundedUser = userObj; } }) console.log(foundedUser); if(foundedUser){ string = string.replace(’status’, ‘已登录’) string = string.replace(’email’, foundedUser.email) string = string.replace(’password’, foundedUser.password) }else{ string = string.replace(’status’, ‘未登录,请去登录’) string = string.replace(’email’, ‘没’) string = string.replace(’password’, ‘没’) } response.setHeader(‘Content-Type’, ’text/html;charset=utf-8’) response.write(string) response.end() }在没有Cookie的时候,首页的状态登录之后,后台根据Cookie查询数据库,将用户名与密码传到前台的首页上退出登录将删除Cookie并刷新页面,重新回到未登录的状态Cookie在登录的时候的特点我们得到Cookie的特点:第一次登录的时候,服务器通过 Set-Cookie 响应头设置 Cookie,然后以响应的形式发给浏览器浏览器得到 响应中Cookie 之后,之后每次请求这个域名都要带上这个 Cookie之后服务器读取当时自己设置的 Cookie 就知道登录用户的信息(email)几个关于Cookie的问题1.我在 Chrome 登录了得到 Cookie,用 Safari 访问,Safari 会带上 Cookie 吗no2.Cookie 存在哪Windows 存在 C 盘的一个文件里3.Cookie会被用户篡改吗?可以,例如在谷歌浏览器开发者模式下的application->Cookie中可以手动修改,修改之后,下次发送请求时,附带的就是修改后的CookieJS中也有可以操作cookie的api( 假如换成别的用户的账号,那么还可以登录成功的话,就会存在风险问题.Session 来解决这个问题,防止用户篡改)后端可以强制设置不允许修改Cookie,只要将Cookie的属性设置为Httponly即可(还可以手动改,但是JS改不了,也无法获取),具体语法看 MDN4.Cookie 有效期吗?默认有效期20分钟左右,不同浏览器策略不同(如果浏览器一直开着,那么Cookie不会被删除.如果关闭浏览器,那么浏览器为了安全考虑,20分钟左右后可能会删除Cookie.这也取决于服务器如何设置Cookie的有效期)后端可以强制设置有效期,具体语法看 MDNCookie 遵守同源策略吗?也有,不过跟 AJAX 的同源策略稍微有些不同。当请求 qq.com 下的资源时,浏览器会默认带上 qq.com 对应的 Cookie,不会带上 baidu.com 对应的 Cookie当请求 v.qq.com 下的资源时,浏览器不仅会带上 v.qq.com 的Cookie,还会带上 qq.com 的 Cookie另外 Cookie 还可以根据路径做限制,请自行了解,这个功能用得比较少。需要注意的细节问题为什么前后端都要进行表单验证?前后端都要验证邮箱格式是否正确,账号密码格式是否正确,两次提交的密码是否相同等。因为黑客可以绕过前端的js验证流程,例如黑客可以直接使用curl 进行请求的发送,直接与后台服务器进行交互。如图:所以后台也需要进行表单验证。Cookie如何手动关闭翻译cookie:曲奇饼cache-control:缓存控制 ...

October 4, 2018 · 2 min · jiezi

以登录注册理解Cookie的作用过程

这篇文章是前一篇文章(Cookie理论知识)的实践性理解完整代码:完整代码Cookie在注册登录时的作用过程:注册注册时把账号密码写入数据库登录第一次登录时服务器给浏览器发送Cookie.后台的登录路由代码(nodejs):else if (path === ‘/sign_in’ && method === ‘POST’) { readBody(request).then((body) => { let strings = body.split(’&’) // [’email=1’, ‘password=2’, ‘password_confirmation=3’] let hash = {} strings.forEach((string) => { // string == ’email=1’ let parts = string.split(’=’) // [’email’, ‘1’] let key = parts[0] let value = parts[1] hash[key] = decodeURIComponent(value) // hash[’email’] = ‘1’ }) let { email, password } = hash var users = fs.readFileSync(’./db/users’, ‘utf8’) try { users = JSON.parse(users) // [] } catch (exception) { users = [] } let found for (let i = 0; i < users.length; i++) { if (users[i].email === email && users[i].password === password) { found = true break } } if (found) {//关键在这里,验证成功,设置登录Cookie为登录的邮箱,并放在响应里发给浏览器 response.setHeader(‘Set-Cookie’, sign_in_email=${email}) response.statusCode = 200 } else { response.statusCode = 401 } response.end() }) }在登录成功的一瞬间,需要后台设置一个Cookie,记录一下登陆的用户id(这里用邮箱表示,代码在上面),然后发响应给浏览器例如在服务器端设置响应头:set-cookies:user_email=1@mtt.com这时候我们查看响应:发现响应头已经设置cookie.然后跳转到主页,这时候我们查看跳转到主页的请求:发现跳转到主页的请求头中包含cookie字段(以后访问这个域名都会带着这个Cookie)!所以,就像上篇文章说的:如果服务器给了浏览器一个setcookie的响应头,那么这个浏览器以后所有的请求,只要是相同的源(即就是上次给我发送Cookie的那个域名,域名和端口相同),那就么就会把当时服务器发给这个浏览器的Cookie带着以后,浏览器一旦访问这个路径,浏览器就会附上这段 Cookie 发送给服务器即:第一次请求,服务器为浏览器设置Cookie.下次请求,浏览器带上Cookie,发送给服务器.第一次登录的时候,服务器给浏览器的响应设置一个Cookie,set-cookies:user_email=1@mtt.com,然后当浏览器下次进行请求的时候,发现Cookie中有名为User_email的Cookie,而且我发送请求的域名还是上次发给我带Cookie的响应的那个域名.那么就无需再次登录了.相当于服务器给浏览器发了进入门票,下次或下下次浏览器在进入服务器的时候给服务器看票就可以了后台读取Cookie保留登录状态与删除Cookie退出登录状态首页代码:<body> <h1>我是首页</h1> <div class=""> <a href="./sign_up">注册</a> <a href="./sign_in">登录</a> </div> <h1>你的状态是:status</h1> <h1>你的邮箱账号是:email</h1> <h1>你的密码是:password</h1> <a href=“javascript:;” id=“logOffBtn”>退出登录(删除cookie)</a></body><script>logOffBtn.addEventListener(“click”, () => { // 删除一个现存 Cookie 的唯一方法,是设置它的expires属性为一个过去的日期。 document.cookie = ‘sign_in_email=;expires=Thu, 01-Jan-1970 00:00:01 GMT’ window.location = “/” })</script>后台路由代码if (path === ‘/’) { response.statusCode = 200 let string = fs.readFileSync(’./index.html’) string = string.toString(); var users = fs.readFileSync(’./db/users’, ‘utf8’) users = JSON.parse(users)//转化为user对象数组 console.log(users); let cookies = request.headers.cookie || ‘’//[’email=111’, ‘asdasd=111’] cookies = cookies.split("; “) let hash={} cookies.forEach((string)=>{ let parts = string.split("=”) let key = parts[0] let value = parts[1] hash[key] = value; }) let eamil = hash.sign_in_email let foundedUser users.forEach((userObj)=>{ if(userObj.email===eamil){ foundedUser = userObj; } }) console.log(foundedUser); if(foundedUser){ string = string.replace(’status’, ‘已登录’) string = string.replace(’email’, foundedUser.email) string = string.replace(’password’, foundedUser.password) }else{ string = string.replace(’status’, ‘未登录,请去登录’) string = string.replace(’email’, ‘没’) string = string.replace(’password’, ‘没’) } response.setHeader(‘Content-Type’, ’text/html;charset=utf-8’) response.write(string) response.end() }在没有Cookie的时候,首页的状态登录之后,后台根据Cookie查询数据库,将用户名与密码传到前台的首页上退出登录将删除Cookie并刷新页面,重新回到未登录的状态Cookie在登录的时候的特点我们得到Cookie的特点:第一次登录的时候,服务器通过 Set-Cookie 响应头设置 Cookie,然后以响应的形式发给浏览器浏览器得到 响应中Cookie 之后,之后每次请求这个域名都要带上这个 Cookie之后服务器读取当时自己设置的 Cookie 就知道登录用户的信息(email)几个关于Cookie的问题1.我在 Chrome 登录了得到 Cookie,用 Safari 访问,Safari 会带上 Cookie 吗no2.Cookie 存在哪Windows 存在 C 盘的一个文件里3.Cookie会被用户篡改吗?可以,例如在谷歌浏览器开发者模式下的application->Cookie中可以手动修改,修改之后,下次发送请求时,附带的就是修改后的CookieJS中也有可以操作cookie的api( 假如换成别的用户的账号,那么还可以登录成功的话,就会存在风险问题.Session 来解决这个问题,防止用户篡改)后端可以强制设置不允许修改Cookie,只要将Cookie的属性设置为Httponly即可(还可以手动改,但是JS改不了,也无法获取),具体语法看 MDN4.Cookie 有效期吗?默认有效期20分钟左右,不同浏览器策略不同(如果浏览器一直开着,那么Cookie不会被删除.如果关闭浏览器,那么浏览器为了安全考虑,20分钟左右后可能会删除Cookie.这也取决于服务器如何设置Cookie的有效期)后端可以强制设置有效期,具体语法看 MDNCookie 遵守同源策略吗?也有,不过跟 AJAX 的同源策略稍微有些不同。当请求 qq.com 下的资源时,浏览器会默认带上 qq.com 对应的 Cookie,不会带上 baidu.com 对应的 Cookie当请求 v.qq.com 下的资源时,浏览器不仅会带上 v.qq.com 的Cookie,还会带上 qq.com 的 Cookie另外 Cookie 还可以根据路径做限制,请自行了解,这个功能用得比较少。需要注意的细节问题为什么前后端都要进行表单验证?前后端都要验证邮箱格式是否正确,账号密码格式是否正确,两次提交的密码是否相同等。因为黑客可以绕过前端的js验证流程,例如黑客可以直接使用curl 进行请求的发送,直接与后台服务器进行交互。如图:所以后台也需要进行表单验证。Cookie如何手动关闭翻译cookie:曲奇饼cache-control:缓存控制 ...

October 2, 2018 · 2 min · jiezi

Laravel核心解读--Cookie源码分析

Laravel Cookie源码分析使用Cookie的方法为了安全起见,Laravel 框架创建的所有 Cookie 都经过加密并使用一个认证码进行签名,这意味着如果客户端修改了它们则需要对其进行有效性验证。我们使用 IlluminateHttpRequest 实例的 cookie 方法从请求中获取 Cookie 的值:$value = $request->cookie(’name’);也可以使用Facade Cookie来读取Cookie的值:Cookie::get(’name’, ‘’);//第二个参数的意思是读取不到name的cookie值的话,返回空字符串添加Cookie到响应可以使用 响应对象的cookie 方法将一个 Cookie 添加到返回的 IlluminateHttpResponse 实例中,你需要传递 Cookie 的名称、值、以及有效期(分钟)到这个方法:return response(‘Learn Laravel Kernel’)->cookie( ‘cookie-name’, ‘cookie-value’, $minutes);响应对象的cookie 方法接收的参数和 PHP 原生函数 setcookie 的参数一致:return response(‘Learn Laravel Kernel’)->cookie( ‘cookie-name’, ‘cookie-value’, $minutes, $path, $domain, $secure, $httpOnly);还可使用Facade Cookie的queue方法以队列的形式将Cookie添加到响应:Cookie::queue(‘cookie-name’, ‘cookie-value’);queue 方法接收 Cookie 实例或创建 Cookie 所必要的参数作为参数,这些 Cookie 会在响应被发送到浏览器之前添加到响应中。接下来我们来分析一下Laravel中Cookie服务的实现原理。Cookie服务注册之前在讲服务提供器的文章里我们提到过,Laravel在BootStrap阶段会通过服务提供器将框架中涉及到的所有服务注册到服务容器里,这样在用到具体某个服务时才能从服务容器中解析出服务来,所以Cookie服务的注册也不例外,在config/app.php中我们能找到Cookie对应的服务提供器和门面。‘providers’ => [ /* * Laravel Framework Service Providers… / …… IlluminateCookieCookieServiceProvider::class, ……] ‘aliases’ => [ …… ‘Cookie’ => IlluminateSupportFacadesCookie::class, ……]Cookie服务的服务提供器是 IlluminateCookieCookieServiceProvider ,其源码如下:<?phpnamespace IlluminateCookie;use IlluminateSupportServiceProvider;class CookieServiceProvider extends ServiceProvider{ /* * Register the service provider. * * @return void / public function register() { $this->app->singleton(‘cookie’, function ($app) { $config = $app->make(‘config’)->get(‘session’); return (new CookieJar)->setDefaultPathAndDomain( $config[‘path’], $config[‘domain’], $config[‘secure’], $config[‘same_site’] ?? null ); }); }}在CookieServiceProvider里将IlluminateCookieCookieJar类的对象注册为Cookie服务,在实例化时会从Laravel的config/session.php配置中读取出path、domain、secure这些参数来设置Cookie服务用的默认路径和域名等参数,我们来看一下CookieJar里setDefaultPathAndDomain的实现:namespace IlluminateCookie;class CookieJar implements JarContract{ /* * 设置Cookie的默认路径和Domain * * @param string $path * @param string $domain * @param bool $secure * @param string $sameSite * @return $this / public function setDefaultPathAndDomain($path, $domain, $secure = false, $sameSite = null) { list($this->path, $this->domain, $this->secure, $this->sameSite) = [$path, $domain, $secure, $sameSite]; return $this; }}它只是把这些默认参数保存到CookieJar对象的属性中,等到make生成SymfonyComponentHttpFoundationCookie对象时才会使用它们。生成Cookie上面说了生成Cookie用的是Response对象的cookie方法,Response的是利用Laravel的全局函数cookie来生成Cookie对象然后设置到响应头里的,有点乱我们来看一下源码class Response extends BaseResponse{ /* * Add a cookie to the response. * * @param SymfonyComponentHttpFoundationCookie|mixed $cookie * @return $this / public function cookie($cookie) { return call_user_func_array([$this, ‘withCookie’], func_get_args()); } /* * Add a cookie to the response. * * @param SymfonyComponentHttpFoundationCookie|mixed $cookie * @return $this / public function withCookie($cookie) { if (is_string($cookie) && function_exists(‘cookie’)) { $cookie = call_user_func_array(‘cookie’, func_get_args()); } $this->headers->setCookie($cookie); return $this; }}看一下全局函数cookie的实现:/* * Create a new cookie instance. * * @param string $name * @param string $value * @param int $minutes * @param string $path * @param string $domain * @param bool $secure * @param bool $httpOnly * @param bool $raw * @param string|null $sameSite * @return IlluminateCookieCookieJar|SymfonyComponentHttpFoundationCookie /function cookie($name = null, $value = null, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true, $raw = false, $sameSite = null){ $cookie = app(CookieFactory::class); if (is_null($name)) { return $cookie; } return $cookie->make($name, $value, $minutes, $path, $domain, $secure, $httpOnly, $raw, $sameSite);}通过cookie函数的@return标注我们能知道它返回的是一个IlluminateCookieCookieJar对象或者是SymfonyComponentHttpFoundationCookie对象。既cookie函数在无接受参数时返回一个CookieJar对象,在有Cookie参数时调用了CookieJar的make方法返回一个SymfonyComponentHttpFoundationCookie对象。拿到Cookie对象后程序接着流程往下走把Cookie设置到Response对象的headers属性里,`headers`属性引用了SymfonyComponentHttpFoundationResponseHeaderBag对象class ResponseHeaderBag extends HeaderBag{ public function setCookie(Cookie $cookie) { $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; $this->headerNames[‘set-cookie’] = ‘Set-Cookie’; }}我们可以看到这里只是把Cookie对象暂存到了headers对象里,真正把Cookie发送到浏览器是在Laravel返回响应时发生的,在Laravel的public/index.php里:$response->send();Laravel的Response继承自Symfony的Response,send方法定义在Symfony的Response里namespace SymfonyComponentHttpFoundation;class Response{ /* * Sends HTTP headers and content. * * @return $this / public function send() { $this->sendHeaders(); $this->sendContent(); if (function_exists(‘fastcgi_finish_request’)) { fastcgi_finish_request(); } elseif (!in_array(PHP_SAPI, array(‘cli’, ‘phpdbg’), true)) { static::closeOutputBuffers(0, true); } return $this; } public function sendHeaders() { // headers have already been sent by the developer if (headers_sent()) { return $this; } // headers foreach ($this->headers->allPreserveCase() as $name => $values) { foreach ($values as $value) { header($name.’: ‘.$value, false, $this->statusCode); } } // status header(sprintf(‘HTTP/%s %s %s’, $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); return $this; } /* * Returns the headers, with original capitalizations. * * @return array An array of headers / public function allPreserveCase() { $headers = array(); foreach ($this->all() as $name => $value) { $headers[isset($this->headerNames[$name]) ? $this->headerNames[$name] : $name] = $value; } return $headers; } public function all() { $headers = parent::all(); foreach ($this->getCookies() as $cookie) { $headers[‘set-cookie’][] = (string) $cookie; } return $headers; }} 在Response的send方法里发送响应头时将Cookie数据设置到了Http响应首部的Set-Cookie字段里,这样当响应发送给浏览器后浏览器就能保存这些Cookie数据了。至于用门面Cookie::queue以队列的形式设置Cookie其实也是将Cookie暂存到了CookieJar对象的queued属性里namespace IlluminateCookie;class CookieJar implements JarContract{ public function queue(…$parameters) { if (head($parameters) instanceof Cookie) { $cookie = head($parameters); } else { $cookie = call_user_func_array([$this, ‘make’], $parameters); } $this->queued[$cookie->getName()] = $cookie; } public function queued($key, $default = null) { return Arr::get($this->queued, $key, $default); }}然后在web中间件组里边有一个IlluminateCookieMiddlewareAddQueuedCookiesToResponse中间件,它在响应返回给客户端之前将暂存在queued属性里的Cookie设置到了响应的headers对象里:namespace IlluminateCookieMiddleware;use Closure;use IlluminateContractsCookieQueueingFactory as CookieJar;class AddQueuedCookiesToResponse{ /* * The cookie jar instance. * * @var IlluminateContractsCookieQueueingFactory / protected $cookies; /* * Create a new CookieQueue instance. * * @param IlluminateContractsCookieQueueingFactory $cookies * @return void / public function __construct(CookieJar $cookies) { $this->cookies = $cookies; } /* * Handle an incoming request. * * @param IlluminateHttpRequest $request * @param Closure $next * @return mixed / public function handle($request, Closure $next) { $response = $next($request); foreach ($this->cookies->getQueuedCookies() as $cookie) { $response->headers->setCookie($cookie); } return $response; }这样在Response对象调用send方法时也会把通过Cookie::queue()设置的Cookie数据设置到Set-Cookie响应首部中去了。读取CookieLaravel读取请求中的Cookie值$value = $request->cookie(’name’); 其实是Laravel的Request对象直接去读取Symfony请求对象的cookies来实现的, 我们在写Laravel Request对象的文章里有提到它依赖于Symfony的Request, Symfony的Request在实例化时会把PHP里那些$_POST、$_COOKIE全局变量抽象成了具体对象存储在了对应的属性中。namespace IlluminateHttp;class Request extends SymfonyRequest implements Arrayable, ArrayAccess{ public function cookie($key = null, $default = null) { return $this->retrieveItem(‘cookies’, $key, $default); } protected function retrieveItem($source, $key, $default) { if (is_null($key)) { return $this->$source->all(); } //从Request的cookies属性中获取数据 return $this->$source->get($key, $default); }}关于通过门面Cookie::get()读取Cookie的实现我们可以看下Cookie门面源码的实现,通过源码我们知道门面Cookie除了通过外观模式代理Cookie服务外自己也定义了两个方法:<?phpnamespace IlluminateSupportFacades;/* * @see IlluminateCookieCookieJar /class Cookie extends Facade{ /* * Determine if a cookie exists on the request. * * @param string $key * @return bool / public static function has($key) { return ! is_null(static::$app[‘request’]->cookie($key, null)); } /* * Retrieve a cookie from the request. * * @param string $key * @param mixed $default * @return string / public static function get($key = null, $default = null) { return static::$app[‘request’]->cookie($key, $default); } /* * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return ‘cookie’; }}Cookie::get()和Cookie::has()是门面直接读取Request对象cookies属性里的Cookie数据。Cookie加密关于对Cookie的加密可以看一下IlluminateCookieMiddlewareEncryptCookies中间件的源码,它的子类AppHttpMiddlewareEncryptCookies是Laravelweb中间件组里的一个中间件,如果想让客户端的Javascript程序能够读Laravel设置的Cookie则需要在AppHttpMiddlewareEncryptCookies的$exception里对Cookie名称进行声明。Laravel中Cookie模块大致的实现原理就梳理完了,希望大家看了我的源码分析后能够清楚Laravel Cookie实现的基本流程这样在遇到困惑或者无法通过文档找到解决方案时可以通过阅读源码看看它的实现机制再相应的设计解决方案。本文已经收录在系列文章Laravel源码学习里,欢迎访问阅读。 ...

September 2, 2018 · 4 min · jiezi