实用,完整的HTTP cookie指南,互联网大厂面试

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
img

正文

ImmutableMultiDict([(‘id’, ‘3db4adj3d’)])

127.0.0.1 - - [27/May/2020 11:27:55] “HEAD /about/ HTTP/1.1” 200 -

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

url -I http://127.0.0.1:5000/contact/ --cookie cookies

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

ImmutableMultiDict([])

127.0.0.1 - - [27/May/2020 11: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_header Set-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.comDomain 属性是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 文件:

from flask import Flask, make_response, render_template

app = Flask(name)

@app.route(“/”, methods=[“GET”])

def index():

return render_template(“index.html”)

@app.route(“/get-cookie/”, methods=[“GET”])

def get_cookie():

response = make_response(“Here, take some cookie!”)

response.set_cookie(key=“id”, value=“3db4adj3d”)

return response

以下是 templates/index.html 模板:

Title

FETCH

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

const button = document.getElementsByTagName(“button”)[0];

button.addEventListener(“click”, function() {

getACookie();

});

function getACookie() {

fetch(“/get-cookie/”)

.then(response => {

// make sure to check response.ok in the real world!

return response.text();

})

.then(text => console.log(text));

}

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

对 Flask 应用程序进行一些更改,多加一个路由:

from flask import Flask, make_response, request, render_template, jsonify

app = Flask(name)

@app.route(“/”, methods=[“GET”])

def index():

return render_template(“index.html”)

@app.route(“/get-cookie/”, methods=[“GET”])

def get_cookie():

response = make_response(“Here, take some cookie!”)

response.set_cookie(key=“id”, value=“3db4adj3d”)

return response

@app.route(“/api/cities/”, methods=[“GET”])

def cities():

if request.cookies[“id”] == “3db4adj3d”:

cities = [{“name”: “Rome”, “id”: 1}, {“name”: “Siena”, “id”: 2}]

return jsonify(cities)

return jsonify(msg=“Ops!”)

另外,调整一下 JS 代码,用于下请求刚新增的路由:

const button = document.getElementsByTagName(“button”)[0];

button.addEventListener(“click”, function() {

getACookie().then(() => getData());

});

function getACookie() {

return fetch(“/get-cookie/”).then(response => {

// make sure to check response.ok in the real world!

return Promise.resolve(“All good, fetch the data”);

});

}

function getData() {

fetch(“/api/cities/”)

.then(response => {

// make sure to check response.ok in the real world!

return response.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=development FLASK_APP=flask_app.py flask run

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

Title

FETCH

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

button.addEventListener(“click”, function() {

getACookie().then(() => getData());

});

function getACookie() {

return fetch(“http://localhost:5000/get-cookie/”).then(response => {

// make sure to check response.ok in the real world!

return Promise.resolve(“All good, fetch the data”);

});

}

function getData() {

fetch(“http://localhost:5000/api/cities/”)

.then(response => {

// make sure to check response.ok in the real world!

return response.json();

})

.then(json => console.log(json));

}

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

npx serve

此命令为您提供了要连接的本地地址/端口,例如http://localhost:42091/。 访问页面并尝试在浏览器控制台打开的情况下单击按钮。 在控制台中,可以看到:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/get-cookie/. (Reason: CORS header ‘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:

pip install flask-cors

然后将 CORS 应用于 Flask:

from flask import Flask, make_response, request, render_template, jsonify

from flask_cors import CORS

app = Flask(name)

CORS(app=app)

@app.route(“/”, methods=[“GET”])

def index():

return render_template(“index.html”)

@app.route(“/get-cookie/”, methods=[“GET”])

def get_cookie():

response = make_response(“Here, take some cookie!”)

response.set_cookie(key=“id”, value=“3db4adj3d”)

return response

@app.route(“/api/cities/”, methods=[“GET”])

def cities():

if request.cookies[“id”] == “3db4adj3d”:

cities = [{“name”: “Rome”, “id”: 1}, {“name”: “Siena”, “id”: 2}]

return jsonify(cities)

return jsonify(msg=“Ops!”)

现在尝试在浏览器控制台打开的情况下再次单击按钮。在控制台中你应该看到

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/api/cities/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)

尽管我们犯了同样的错误,但这次的罪魁祸首是第二个路由。

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

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

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

const button = document.getElementsByTagName(“button”)[0];

button.addEventListener(“click”, function() {

getACookie().then(() => getData());

});

function getACookie() {

return fetch(“http://localhost:5000/get-cookie/”, {

credentials: “include”

}).then(response => {

// make sure to check response.ok in the real world!

return Promise.resolve(“All good, fetch the data”);

});

}

function getData() {

fetch(“http://localhost:5000/api/cities/”, {

credentials: “include”

})

.then(response => {

// make sure to check response.ok in the real world!

return response.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-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/get-cookie/. (Reason: expected ‘true’ in CORS header ‘Access-Control-Allow-Credentials’).

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

CORS(app=app, supports_credentials=True)

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

  • credentials: “include” 用于前端的 fetch 请求中

  • Access-Control-Allow-CredentialsAccess-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 -I http://serene-bastion-01422.herokuapp.com/get-secure-cookie/ --cookie-jar -

相反,通过HTTPS,cookie 出现在cookie jar中:

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

cookie jar 文件:

serene-bastion-01422.herokuapp.com FALSE / TRUE 0

不要被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 在第三方网站插入一张看不见的图片。

React

  • 介绍一下react

  • React单项数据流

  • react生命周期函数和react组件的生命周期

  • react和Vue的原理,区别,亮点,作用

  • reactJs的组件交流

  • 有了解过react的虚拟DOM吗,虚拟DOM是怎么对比的呢

  • 项目里用到了react,为什么要选择react,react有哪些好处

  • 怎么获取真正的dom

  • 选择react的原因

  • react的生命周期函数

  • setState之后的流程

  • react高阶组件知道吗?

  • React的jsx,函数式编程

  • react的组件是通过什么去判断是否刷新的

  • 如何配置React-Router

  • 路由的动态加载模块

  • Redux中间件是什么东西,接受几个参数

  • redux请求中间件如何处理并发

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
载图像。

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

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

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

React

  • 介绍一下react

  • React单项数据流

  • react生命周期函数和react组件的生命周期

  • react和Vue的原理,区别,亮点,作用

  • reactJs的组件交流

  • 有了解过react的虚拟DOM吗,虚拟DOM是怎么对比的呢

  • 项目里用到了react,为什么要选择react,react有哪些好处

  • 怎么获取真正的dom

  • 选择react的原因

  • react的生命周期函数

  • setState之后的流程

  • react高阶组件知道吗?

  • React的jsx,函数式编程

  • react的组件是通过什么去判断是否刷新的

  • 如何配置React-Router

  • 路由的动态加载模块

  • Redux中间件是什么东西,接受几个参数

  • redux请求中间件如何处理并发

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-CDCXRmrC-1713558319384)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值