首页 » 网站推广 » phpcookiejscookie技巧_必需知道实用完整的HTTP cookie指南

phpcookiejscookie技巧_必需知道实用完整的HTTP cookie指南

访客 2024-10-30 0

扫一扫用手机浏览

文章目录 [+]

Cookies 具有很多隐私问题,多年来一贯受到严格的监管。

在本文中,紧张侧重于技能方面:学习如何在前端和后端创建,利用 HTTP cookie。

phpcookiejscookie技巧_必需知道实用完整的HTTP cookie指南

后端配置

后端示例是Flask编写的。
如果你想随着学习,可以创建一个新的Python虚拟环境,移动到个中并安装Flask

phpcookiejscookie技巧_必需知道实用完整的HTTP cookie指南
(图片来自网络侵删)

mkdircookies&&cd$_python3-mvenvvenvsourcevenv/bin/activatepipinstallFlask

在项目文件夹中创建一个名为flask app.py的新文件,并利用本文的示例在本地进行实验。

谁创建 cookies ?

首先,cookies 从何而来?谁创建 cookies ?

虽然可以利用document.cookie在浏览器中创建 cookie,但大多数情形下,后真个任务是在将相应客户端要求之前在要求中设置 cookie。

后端是指可以通过以下办法创建 Cookie:

后端实际运用程序的代码(Python、JavaScript、PHP、Java)相应要求的Web做事器(Nginx,Apache)

后端可以在 HTTP 要求求中 Set-Cookie 属性来设置 cookie,它是由键/值对以及可选属性组成的相应字符串:

Set-Cookie:myfirstcookie=somecookievalue

什么时候须要创建 cookie?这取决于需求。

cookie 是大略的字符串。
在项目文件夹中创建一个名为flask_app.py的Python文件,并输入以下内容:

fromflaskimportFlask,make_responseapp=Flask(__name__)@app.route("/index/",methods=["GET"])defindex():response=make_response("Here,takesomecookie!")response.headers["Set-Cookie"]="myfirstcookie=somecookievalue"returnresponse

然后运行运用程序:

FLASK_ENV=developmentFLASK_APP=flask_app.pyflaskrun

当该运用程序运行时,用户访问http://127.0.0.1:5000/index/,后端将设置一个具有键/值对的名为Set-Cookie的相应标头。

(127.0.0.1:5000是开拓中的 Flask 运用程序的默认侦听地址/端口)。

Set-Cookie标头是理解如何创建cookie的关键:

response.headers["Set-Cookie"]="myfirstcookie=somecookievalue"

大多数框架都有自己设置 cookie 的方法,比如Flask的set_cookie()。

如何查看 cookies ?

访问http://127.0.0.1:5000/index/后,后端将在浏览器中设置cookie。
要查看此cookie,可以从浏览器的掌握台调用document.cookie:

或者可以在开拓职员工具中选中Storage选项卡。
单击cookie,会看到 cookie 详细的内容:

在命令行上,还可以利用curl查看后端设置了哪些 cookie

curl-Ihttp://127.0.0.1:5000/index/

可以将 Cookie 保存到文件中以供往后利用:

curl-Ihttp://127.0.0.1:5000/index/--cookie-jarmycookies

在 stdout 上显示 cookie:

curl-Ihttp://127.0.0.1:5000/index/--cookie-jar-

请把稳,没有HttpOnly属性的cookie,在浏览器中可以利用document.cookie上访问,如果设置了 HttpOnly 属性,document.cookie就读取不到。

Set-Cookie:myfirstcookie=somecookievalue;HttpOnly

现在,该cookie 仍将涌如今 Storage 选项卡中,但是 document.cookie返回的是一个空字符串。

从现在开始,为方便起见,利用Flask的 response.set_cookie() 在后端上创建 cookie。

我有一个 cookie,现在怎么办?

你的浏览器得到一个 cookie。
现在怎么办呢?一旦有了 cookie,浏览器就可以将cookie发送回后端。

这有许多用场发如:用户跟踪、个性化,以及最主要的身份验证。

例如,一旦你登录网站,后端就会给你一个cookie:

Set-Cookie:userid=sup3r4n0m-us3r-1d3nt1f13r

为了在每个后续要求中精确识别 我们的身份,后端会检讨来自要求中浏览器的 cookie

要发送Cookie,浏览器会在要求中附加一个Cookie标头:

Cookie:userid=sup3r4n0m-us3r-1d3nt1f13rcookie 可以设置过期韶光: Max-Age 和 expires

默认情形下,cookie 在用户关闭会话时即关闭浏览器时过期。
要持久化cookie,我们可以通过expires或Max-Age属性

Set-Cookie:myfirstcookie=somecookievalue;expires=Tue,09Jun202015:46:52GMT;Max-Age=1209600

把稳:Max-Age优先于expires。

cookie的浸染域是网站路径: path 属性

考虑该后端,该后端在访问http://127.0.0.1:5000/时为其前端设置了一个新的 cookie。
相反,在其他两条路径上,我们打印要求的cookie:

fromflaskimportFlask,make_response,requestapp=Flask(__name__)@app.route("/",methods=["GET"])defindex():response=make_response("Here,takesomecookie!")response.set_cookie(key="id",value="3db4adj3d",path="/about/")returnresponse@app.route("/about/",methods=["GET"])defabout():print(request.cookies)return"Helloworld!"@app.route("/contact/",methods=["GET"])defcontact():print(request.cookies)return"Helloworld!"

运行该运用程序:

FLASK_ENV=developmentFLASK_APP=flask_app.pyflaskrun

在另一个终端中,如果我们与根路由建立连接,则可以在Set-Cookie中看到cookie:

curl-Ihttp://127.0.0.1:5000/--cookie-jarcookiesHTTP/1.0200OKContent-Type:text/html;charset=utf-8Content-Length:23Set-Cookie:id=3db4adj3d;Path=/about/Server:Werkzeug/1.0.1Python/3.8.3Date:Wed,27May202009:21:37GMT

请把稳,此时 cookie 具有Path属性:

Set-Cookie:id=3db4adj3d;Path=/about/

/about/ 路由并保存 cookit

curl-Ihttp://127.0.0.1:5000/about/--cookiecookies

在 Flask 运用程序的终端中运行如下命令,可以看到:

ImmutableMultiDict([('id','3db4adj3d')])127.0.0.1--[27/May/202011:27:55]"HEAD/about/HTTP/1.1"200-

正如预期的那样,cookie 返回到后端。
现在考试测验访问 /contact/ 路由:

url-Ihttp://127.0.0.1:5000/contact/--cookiecookies

在 Flask 运用程序的终端中运行如下命令,可以看到:

ImmutableMultiDict([])127.0.0.1--[27/May/202011:29:00]"HEAD/contact/HTTP/1.1"200-

这解释啥?cookie 的浸染域是Path 。
具有给定路径属性的cookie不能被发送到另一个不干系的路径,纵然这两个路径位于同一域中。

这是cookie权限的第一层。

在cookie创建过程中省略Path时,浏览器默认为/。

cookie 的浸染域是域名: domain 属性

cookie 的 Domain 属性的值掌握浏览器是否该当接管cookie以及cookie返回的位置。

让我们看一些例子。

主机不匹配(缺点的主机)

查看 https://serene-bastion-01422.herokuapp.com/get-wrong-domain-cookie/设置的cookie:

Set-Cookie:coookiename=wr0ng-d0m41n-c00k13;Domain=api.valentinog.com

这里的 cookie 来自serene-bastion-01422.herokuapp.com,但是Domain属性具有api.valentinog.com。

浏览器没有其他选择来谢绝这个 cookie。
比如 Chrome 会给出一个警告(Firefox没有)

主机不匹配(子域名)

查看 https://serene-bastion-01422.herokuapp.com/get-wrong-subdomain-cookie/设置的cookie:

Set-Cookie:coookiename=wr0ng-subd0m41n-c00k13;Domain=secure-brushlands-44802.herokuapp.com

这里的 Cookie 来自serene-bastion-01422.herokuapp.com,但“Domain”属性是secure-brushlands-44802.herokuapp.com。

它们在相同的域上,但是子域名不同。
同样,浏览器也谢绝此cookie:

主机匹配(全体域)

查看 https://www.valentinog.com/get-domain-cookie.html设置的cookie:

set-cookie:cookiename=d0m41n-c00k13;Domain=valentinog.com

此cookie是利用 Nginx add_header在Web做事器上设置的:

add_headerSet-Cookie"cookiename=d0m41n-c00k13;Domain=valentinog.com";

这里利用 Nginx 中设置cookie的多种方法。
Cookie 是由 Web 做事器或运用程序的代码设置的,对付浏览器来说无关紧要。

主要的是 cookie 来自哪个域。

在此浏览器将愉快地接管cookie,由于Domain中的主机包括cookie所来自的主机。

换句话说,valentinog.com包括子域名www.valentinog.com。

同时,对valentinog.com的新要求,cookie 都会携带着,以及任何对valentinog.com子域名的要求。

这是一个附加了Cookie的 www 子域要求:

下面是对另一个自动附加cookie的子域的要求

Cookies 和公共后缀列表

查看 https://serene-bastion-01422.herokuapp.com/get-domain-cookie/:设置的 cookie:

Set-Cookie:coookiename=d0m41n-c00k13;Domain=herokuapp.com

这里的 cookie 来自serene-bas-01422.herokuapp.com,Domain 属性是herokuapp.com。
浏览器在这里该当做什么

你可能认为serene-base-01422.herokuapp.com包含在herokuapp.com域中,因此浏览器该当接管cookie。

相反,它谢绝 cookie,由于它来自公共后缀列表中包含的域。

Public Suffix List(公共后缀列表)。
此列表列举了顶级域名和开放注册的域名。
浏览器禁止此列表上的域名被子域名写入Cookie。

主机匹配(子域)

查看 https://serene-bastion-01422.herokuapp.com/get-subdomain-cookie/:设置的 cookie:

Set-Cookie:coookiename=subd0m41n-c00k13

当域在cookie创建期间被省略时,浏览器会默认在地址栏中显示原始主机,在这种情形下,我的代码会这样做:

response.set_cookie(key="coookiename",value="subd0m41n-c00k13")

当 Cookie 进入浏览器的 Cookie 存储区时,我们看到已运用Domain :

现在,我们有来自serene-bastion-01422.herokuapp.com 的 cookie, 那 cookie 现在该当送到哪里?

如果你访问https://serene-bastion-01422.herokuapp.com/,则 cookie 随要求一起涌现:

但是,如果访问herokuapp.com,则 cookie 不会随要求一起涌现:

概括地说,浏览器利用以下启示式规则来决定如何处理cookies(这里的发送者主机指的是你访问的实际网址):

如果“Domain”中的域或子域与访问的主机不匹配,则完备谢绝 Cookie如果 Domain 的值包含在公共后缀列表中,则谢绝 cookie如果Domain 中的域或子域与访问在主机匹配,则接管 Cookie

一旦浏览器接管了cookie,并且即将发出要求,它就会说:

如果要求主机与我在Domain中看到的值完备匹配,则会回传 cookie如果要求主机是与我在“Domain”中看到的值完备匹配的子域,则将回传 cookie如果要求主机是sub.example.dev之类的子域,包含在example.dev之类的 Domain 中,则将回传 cookie如果要求主机是例如example.dev之类的主域,而 Domain 是sub.example.dev之类,则不会回传cookie。

Domain 和 Path 属性一贯是 cookie 权限的第二层。

Cookies可以通过AJAX要求通报

Cookies 可以通过AJAX要求传播。
AJAX 要求是利用 JS (XMLHttpRequest或Fetch)进行的异步HTTP要求,用于获取数据并将其发送回后端。

考虑 Flask的另一个示例,个中有一个模板,该模板又会加载 JS 文件:

fromflaskimportFlask,make_response,render_templateapp=Flask(__name__)@app.route("/",methods=["GET"])defindex():returnrender_template("index.html")@app.route("/get-cookie/",methods=["GET"])defget_cookie():response=make_response("Here,takesomecookie!")response.set_cookie(key="id",value="3db4adj3d")returnresponse

以下是 templates/index.html 模板:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><button>FETCH</button></body><scriptsrc="{{url_for('static',filename='index.js')}}"></script></html>

下面是 static/index.js 的内容:

constbutton=document.getElementsByTagName("button")[0];button.addEventListener("click",function(){getACookie();});functiongetACookie(){fetch("/get-cookie/").then(response=>{//makesuretocheckresponse.okintherealworld!returnresponse.text();}).then(text=>console.log(text));}

当访问http://127.0.0.1:5000/时,我们会看到一个按钮。
通过单击按钮,我们向/get-cookie/发出获取要求并获取Cookie。
正如预期的那样,cookie 落在浏览器的 Cookie storage中。

对 Flask 运用程序进行一些变动,多加一个路由:

fromflaskimportFlask,make_response,request,render_template,jsonifyapp=Flask(__name__)@app.route("/",methods=["GET"])defindex():returnrender_template("index.html")@app.route("/get-cookie/",methods=["GET"])defget_cookie():response=make_response("Here,takesomecookie!")response.set_cookie(key="id",value="3db4adj3d")returnresponse@app.route("/api/cities/",methods=["GET"])defcities():ifrequest.cookies["id"]=="3db4adj3d":cities=[{"name":"Rome","id":1},{"name":"Siena","id":2}]returnjsonify(cities)returnjsonify(msg="Ops!")

其余,调度一下 JS 代码,用于下要求刚新增的路由:

constbutton=document.getElementsByTagName("button")[0];button.addEventListener("click",function(){getACookie().then(()=>getData());});functiongetACookie(){returnfetch("/get-cookie/").then(response=>{//makesuretocheckresponse.okintherealworld!returnPromise.resolve("Allgood,fetchthedata");});}functiongetData(){fetch("/api/cities/").then(response=>{//makesuretocheckresponse.okintherealworld!returnresponse.json();}).then(json=>console.log(json));

当访问http://127.0.0.1:5000/时,我们会看到一个按钮。
通过单击按钮,我们向/get-cookie/发出获取要求以获取Cookie。
Cookie涌现后,我们就会对/api/cities/再次发出Fetch要求。

在浏览器的掌握台中,可以看到要求回来 的数据。
其余,在开拓者工具的Network选项卡中,可以看到一个名为Cookie的头,这是通过AJAX要求传给后端。

只要前端与后端在同一高下文中,在前端和后端之间来回交流cookie就可以正常事情:我们说它们来自同源。

这是由于默认情形下,Fetch 仅在要求到达触发要求的来源时才发送凭据,即 Cookie。

cookie 不能总是通过AJAX要求通报

考虑另一种情形,在后端独立运行,可以这样启动运用程序:

FLASK_ENV=developmentFLASK_APP=flask_app.pyflaskrun

现在,在 Flask 运用程序之外的其他文件夹中,创建index.html:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><button>FETCH</button></body><scriptsrc="index.js"></script></html>

利用以下代码在同一文件夹中创建一个名为index.js的 JS 文件:

button.addEventListener("click",function(){getACookie().then(()=>getData());});functiongetACookie(){returnfetch("http://localhost:5000/get-cookie/").then(response=>{//makesuretocheckresponse.okintherealworld!returnPromise.resolve("Allgood,fetchthedata");});}functiongetData(){fetch("http://localhost:5000/api/cities/").then(response=>{//makesuretocheckresponse.okintherealworld!returnresponse.json();}).then(json=>console.log(json));}

在同一文件夹中,从终端运行:

npxserve

此命令为您供应了要连接确当地地址/端口,例如http://localhost:42091/。
访问页面并考试测验在浏览器掌握台打开的情形下单击按钮。
在掌握台中,可以看到:

Cross-OriginRequestBlocked:TheSameOriginPolicydisallowsreadingtheremoteresourceathttp://localhost:5000/get-cookie/.(Reason:CORSheader‘Access-Control-Allow-Origin’missing)

由于 http://localhost:5000/ 与http://localhost:42091/.不同。
它们是不同的域,因此会 CORS 的限定。

处理 CORS

CORS 是一个 W3C 标准,全称是“跨域资源共享”(Cross-origin resource sharing)。
它许可浏览器向跨域的做事器,发出XMLHttpRequest要求,从而战胜了 AJAX 只能同源利用的限定。

全体 CORS 通信过程,都是浏览器自动完成,不须要用户参与。
对付开拓者来说,CORS 通信与普通的 AJAX 通信没有差别,代码完备一样。
浏览器一旦创造 AJAX 要求跨域,就会自动添加一些附加的头信息,有时还会多出一次附加的要求,但用户不会有感知。
因此,实现 CORS 通信的关键是做事器。
只要做事器实现了 CORS 接口,就可以跨域通信。

默认情形下,除非做事器设置了Access-Control-Allow-Origin的特定HTTP标头,否则浏览器将阻挡AJAX对非相同来源的远程资源的要求。

要办理此第一个缺点,我们须要为Flask配置CORS:

pipinstallflask-cors

然后将 CORS 运用于 Flask:

fromflaskimportFlask,make_response,request,render_template,jsonifyfromflask_corsimportCORSapp=Flask(__name__)CORS(app=app)@app.route("/",methods=["GET"])defindex():returnrender_template("index.html")@app.route("/get-cookie/",methods=["GET"])defget_cookie():response=make_response("Here,takesomecookie!")response.set_cookie(key="id",value="3db4adj3d")returnresponse@app.route("/api/cities/",methods=["GET"])defcities():ifrequest.cookies["id"]=="3db4adj3d":cities=[{"name":"Rome","id":1},{"name":"Siena","id":2}]returnjsonify(cities)returnjsonify(msg="Ops!")

现在考试测验在浏览器掌握台打开的情形下再次单击按钮。
在掌握台中你该当看到

Cross-OriginRequestBlocked:TheSameOriginPolicydisallowsreadingtheremoteresourceathttp://localhost:5000/api/cities/.(Reason:CORSheader‘Access-Control-Allow-Origin’missing)

只管我们犯了同样的缺点,但这次的罪魁罪魁是第二个路由。

你可以通过查看 “Network” 标签中的要求来确认,没有发送此类Cookie:

为了在不同来源的Fetch要求中包含cookie,我们必须提credentials 标志(默认情形下,它是相同来源)。

如果没有这个标志,Fetch 就会忽略 cookie,可以这样修复:

constbutton=document.getElementsByTagName("button")[0];button.addEventListener("click",function(){getACookie().then(()=>getData());});functiongetACookie(){returnfetch("http://localhost:5000/get-cookie/",{credentials:"include"}).then(response=>{//makesuretocheckresponse.okintherealworld!returnPromise.resolve("Allgood,fetchthedata");});}functiongetData(){fetch("http://localhost:5000/api/cities/",{credentials:"include"}).then(response=>{//makesuretocheckresponse.okintherealworld!returnresponse.json();}).then(json=>console.log(json));}

credentials: "include" 必须在第一个 Fetch 要求中涌现,才能将Cookie保存在浏览器的Cookie storage 中:

fetch("http://localhost:5000/get-cookie/",{credentials:"include"})

它还必须在第二个要求时涌现,以许可将cookie传输回后端

fetch("http://localhost:5000/api/cities/",{credentials:"include"})

再试一次,我们还须要在后端修复另一个缺点:

Cross-OriginRequestBlocked:TheSameOriginPolicydisallowsreadingtheremoteresourceathttp://localhost:5000/get-cookie/.(Reason:expected‘true’inCORSheader‘Access-Control-Allow-Credentials’).

为了许可在CORS要求中传输cookie,后端还须要设置 Access-Control-Allow-Credentials标头。

CORS(app=app,supports_credentials=True)

要点:为了使Cookie在不同来源之间通过AJAX要求通报,可以这样做:

credentials: "include" 用于前真个 fetch 要求中Access-Control-Allow-Credentials 和 Access-Control-Allow-Origin 用于后端

cookie可以通过AJAX要求通报,但是它们必须遵守我们前面描述的域规则。

Cookie 的 Secure 属性

Secure 属性是说如果一个 cookie 被设置了Secure=true,那么这个cookie只能用https协议发送给做事器,用 http 协议是不发送的。
换句话说,cookie 是在https的情形下创建的,而且他的Secure=true,那么之后你一贯用https访问其他的页面(比如登录之后点击其他子页面),cookie会被发送到做事器,你无需重新登录就可以跳转到其他页面。
但是如果这时你把url改成http协议访问其他页面,你就须要重新登录了,由于这个cookie不能在http协议中发送。

可以这样设置 Secure 属性

response.set_cookie(key="id",value="3db4adj3d",secure=True)

如果要在真实环境中考试测验,请可以运行以下命令,并把稳curl在此处是不通过HTTP保存cookie:

curl-Ihttp://serene-bastion-01422.herokuapp.com/get-secure-cookie/--cookie-jar-

相反,通过HTTPS,cookie 涌如今cookie jar中:

curl-Ihttps://serene-bastion-01422.herokuapp.com/get-secure-cookie/--cookie-jar-

cookie jar 文件:

serene-bastion-01422.herokuapp.comFALSE/TRUE0

不要被Secure欺骗:浏览器通过HTTPS接管cookie,但是一旦cookie进入浏览器,就没有任何保护。

由于带有 Secure 的 Cookie 一样平常也不用于传输敏感数据.

Cookie 的 HttpOnly 属性

如果cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击,盗取cookie内容,这样就增加了cookie的安全性,即便是这样,也不要将主要信息存入cookie。

XSS 全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户真个攻击办法,以是随意马虎被忽略其危害性。
其事理是攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段HTML代码会自动实行,从而达到攻击的目的。
如,盗取用户Cookie、毁坏页面构造、重定向到其它网站等。

如果有设置 HttpOnly 看起来是这样的:

Set-Cookie:"id=3db4adj3d;HttpOnly"

在 Flask 中

response.set_cookie(key="id",value="3db4adj3d",httponly=True)

这样,cookie 设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息。
如果在掌握台中进行检讨,则document.cookie将返回一个空字符串。

何时利用HttpOnly?cookie 该当始终是HttpOnly的,除非有特定的哀求将它们暴露给运行时 JS。

恐怖的 SameSite 属性first-party cookie 和 third-party cookie

查看https://serene-bastion-01422.herokuapp.com/get-cookie/ 中所携带的 Cookie

Set-Cookie:simplecookiename=c00l-c00k13;Path=/

first-party是指你登录或利用的网站所发行的 cookie,而third-party cookie 常为一些广告网站,有陵犯隐私以及安全隐患。

我们将这类 Cookie 称为 first-party。
也便是说,我在浏览器中访问该URL,并且如果我访问相同的URL或该站点的另一个路径(假设Path为/),则浏览器会将cookie发送回该网站。

现在考虑在https://serene-bastion-01422.herokuapp.com/get-frog/上的另一个网页。
该页面设置了一个cookie,此外,它还从https://www.valentinog.com/cookie-frog.jpg托管的远程资源中加载图像。

该远程资源又会自行设置一个cookie:

我们将这种 cookie 称为third-party(第三方) Cookie。

第三方 Cookie 除了用于 CSRF 攻击,还可以用于用户追踪。
比如,Facebook 在第三方网站插入一张看不见的图片。

<imgsrc="facebook.com"style="visibility:hidden;">

浏览器加载上面代码时,就会向 Facebook 发出带有 Cookie 的要求,从而 Facebook 就会知道你是谁,访问了什么网站。

利用 SameSite 属性

Cookie 的SameSite 属性用来限定third-party Cookie,从而减少安全风险。
它可以设置三个值。

StrictLaxNone

Strict最为严格,完备禁止第三方 Cookie,跨站点时,任何情形下都不会发送 Cookie。
换言之,只有当前网页的 URL 与要求目标同等,才会带上 Cookie。

Set-Cookie:CookieName=CookieValue;SameSite=Strict;

这个规则过于严格,可能造成非常不好的用户体验。
比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未上岸状态。

Lax规则稍稍放宽,大多数情形也是不发送第三方 Cookie,但是导航到目标网址的 Get 要求除外。

Set-Cookie:CookieName=CookieValue;SameSite=Lax;

导航到目标网址的 GET 要求,只包括三种情形:链接,预加载要求,GET 表单。
详见下表。

设置了Strict或Lax往后,基本就杜绝了 CSRF 攻击。
当然,条件是用户浏览器支持 SameSite 属性。

Chrome 操持将Lax变为默认设置。
这时,网站可以选择显式关闭SameSite属性,将其设为None。
不过,条件是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

下面的设置无效。

Set-Cookie:widget_session=abc123;SameSite=None

下面的设置有效。

Set-Cookie:widget_session=abc123;SameSite=None;SecureCookies 和 认证

身份验证是 web 开拓中最具寻衅性的任务之一。
关于这个主题彷佛有很多困惑,由于JWT中的基于令牌的身份验证彷佛要取代“旧的”、可靠的模式,如基于会话的身份验证。

来看看 cookie 在这里扮演什么角色。

基于会话的身份验证

身份验证是 cookie 最常见的用例之一。

当你访问一个要求身份验证的网站时,后端将通过凭据提交(例如通过表单)在后台发送一个Set-Cookie标头到前端。

型的会话 cookie 如下所示:

Set-Cookie:sessionid=sty1z3kz11mpqxjv648mqwlx4ginpt6c;expires=Tue,09Jun202015:46:52GMT;HttpOnly;Max-Age=1209600;Path=/;SameSite=Lax

这个Set-Cookie头中,做事器可以包括一个名为session、session id或类似的cookie。

这是浏览器可以清楚看到的唯一标识符。
每当通过身份验证的用户向后端要求新页面时,浏览器就会发回会话cookie。

基于会话的身份验证是有状态的,由于后端必须跟踪每个用户的会话。
这些会话的存储可能是:

数据库像 Redis 这样的键/值存储文件系统

在这三个会话存储中,Redis 之类应优先于数据库或文件系统。

请把稳,基于会话的身份验证与浏览器的会话存储无关。

之以是称为基于会话的会话,是由于用于用户识别的干系数据存在于后真个会话存储中,这与浏览器的会话存储不同。

何时利用基于会话的身份验证

只要能利用就利用它。
基于会话的身份验证是一种最大略、安全、直接的网站身份验证形式。
默认情形下,它可以在Django等所有盛行的web框架上利用。

但是,它的状态特性也是它的紧张缺陷,特殊是当网站是由负载均衡器供应做事时。
在这种情形下,像粘贴会话,或者在集中的Redis存储上存储会话这样的技能会有所帮助。

关于 JWT 的解释

JWT是 JSON Web Tokens的缩写,是一种身份验证机制,近年来越来越盛行。

JWT 非常适宜单页和移动运用程序,但它带来了一系列新寻衅。
想要针对API进行身份验证的前端运用程序的范例流程如下:

前端将凭据发送到后端后端检讨凭据并发回令牌前端在每个后续要求上带上该令牌

这种方法带来的紧张问题是:为了利用户保持登录状态,我将该令牌存储在前真个哪个地方?

对付前端开拓来说,最自然的事情是将令牌保存在localStorage中。
由于许多缘故原由,这很糟糕。

localStorage很随意马虎从 JS 代码访问,而且它很随意马虎成为XSS攻击的目标。

为理解决此问题,大多数开拓职员都将JWT令牌保存在cookie中,以为HttpOnly和Secure可以保护cookie,至少可以免受XSS攻击。

将 SameSite 设置为 strict 就可以完备保护 JWT免受CSRF攻击

设置为SameSite = Strict的新SameSite属性还将保护你的“熟化” JWT免受CSRF攻击。
但是,由于SameSite = Strict不会在跨域要求上发送cookie,因此,这也完备使JWT的用例无效。

那SameSite=Lax呢?此模式许可利用安全的HTTP方法(即GET,HEAD,OPTIONS和TRACE)将 cookie发送回去。
POST 要求不会以任何一种办法传输 cookie。

实际上,将JWT标记存储在cookie或localStorage中都不是好主张。

如果你确实要利用JWT而不是坚持利用基于会话的身份验证并扩展会话存储,则可能要利用带有刷新令牌的JWT来保持用户登录。

总结

自1994年以来,HTTP cookie一贯存在,它们无处不在。

Cookies是大略的文本字符串,但可以通过Domain和Path对其权限进行掌握,具有Secure的Cookie,只能通过 HTTP S进行传输,而可以利用 HttpOnly从 JS隐蔽。

但是,对付所有预期的用场,cookie都可能利用户暴露于攻击和漏洞之中。

浏览器的供应商和Internet工程任务组(Internet Engineering Task Force)年复一年地致力于提高cookie的安全性,最近的一步是SameSite。

那么,什么才算是比较安全cookie?,如下几点:

仅利用 HTTPS尽可能带有 HttpOnly 属性精确的SameSite配置不携带敏感数据

人才们的 【三连】 便是小智不断分享的最大动力,如果本篇博客有任何缺点和建议,欢迎人才们留言,末了,感激大家的不雅观看。

作者:valentinog 译者:前端小智 来源:valentinog

原文:https://gizmodo.com/the-complete-guide-to-cookies-and-all-the-stuff-w-1794247382

标签:

相关文章

Python编程从入门到精通,探索编程之美

编程已经成为现代社会的一项基本技能。Python作为一种简单易学、功能强大的编程语言,在我国教育领域备受关注。本文将从Python...

网站推广 2025-03-02 阅读1 评论0

Scum07代码编程之美与适用方法

编程已成为当今社会不可或缺的技能之一。Scum07代码作为一款经典的编程语言,在我国众多程序员中备受推崇。本文将深入解析Scum0...

网站推广 2025-03-02 阅读1 评论0

Linux环境下的前端代码运行优化与步骤

前端技术逐渐成为软件开发的核心。Linux操作系统因其稳定性、安全性、开放性等特点,成为众多开发者和企业青睐的运行环境。本文将从L...

网站推广 2025-03-02 阅读1 评论0