通常、CSS などのスクリプト以外はメモリに保存されます。など | |
ブラウザ キャッシュの分類
ブラウザがサーバーにリソースを要求すると、まず強力なキャッシュにヒットするかどうかを判断し、失敗した場合は、ネゴシエートされたキャッシュにヒットするかどうかを判断します
強力なキャッシュ
ブラウザがリソースをロードすると、まずローカル キャッシュ リソースの header
に基づいて強力なキャッシュがヒットしたかどうかが判断されます。ヒットした場合、キャッシュはサーバーにリクエストを送信せずに直接使用されます。 (ここでのヘッダーの情報は、expires
および cache-control
を指します)
このフィールドは http1.0 の仕様であり、その値は absolute time 文字列の GMT 形式の時刻文字です。有効期限:2066 年 10 月 18 日月曜日 23:59:59 GMT など。この時間は、このリソースの有効期限を表します。この時間より前に、キャッシュがヒットします。この方法には明らかな欠点があり、有効期限が絶対時間であるため、サーバーとクライアント間の時間のずれが大きい場合、キャッシュの混乱が発生します。そのため、このメソッドは HTTP 1.1 の後のバージョンではすぐに廃止されました。
Cache-Control が http1.1## の場合に表示されるヘッダー# 情報は主に、Cache-Control:max-age=3600## など、相対時間であるこのフィールドの max-age 値を使用して判断されます。 # 、これはリソースの有効期間が 3600 秒であることを意味します。このフィールドに加えて、cache-control には次の一般的に使用される設定値もあります。
no-cache
: キャッシュをネゴシエートし、確認するためにサーバーにリクエストを送信する必要があります。キャッシュを使用するかどうか。 no-store
: キャッシュの使用を無効にし、毎回データを再リクエストします。 public
: エンド ユーザーや CDN などの中間プロキシ サーバーを含むすべてのユーザーがキャッシュできます。 private
: エンド ユーザーのブラウザによってのみキャッシュでき、CDN などのリレー キャッシュ サーバーによってキャッシュすることは許可されません。 Cache-Control と Expires はサーバー構成で同時に有効にすることができます。同時に有効にすると、Cache-Control の優先順位が高くなります。
ネゴシエーション キャッシュ強力なキャッシュが見つからない場合、ブラウザはサーバーにリクエストを送信し、サーバーはこれに続きます。 ヘッダー
の情報は、ネゴシエーション キャッシュがヒットしたかどうかを判断するために使用されます。ヒットした場合は、304 が返され、リソースが更新されていないため、ローカル キャッシュを使用できることがブラウザに通知されます。
(ここでのヘッダー情報は、Last-Modify/If-Modify-Since および ETag/If-None-Match を指します)
Last-Modify/If-Modify-since-
ブラウザが初めてリソースをリクエストすると、サーバーから返されるヘッダーはLast-modify と合わせて、Last-modify はリソースの最終変更時刻を識別する時刻です。
ブラウザがリソースを再度リクエストすると、リクエスト ヘッダーには If-Modify-Since が含まれます。これは、キャッシュする前に返される Last-Modify です。サーバーは If-Modify-Since を受信すると、リソースの最終変更時刻に基づいてキャッシュがヒットしたかどうかを判断します。 キャッシュにヒットした場合、304 が返され、リソースの内容は返されず、Last-Modify も返されません。 欠点:リソースが短期間に変更された場合、Last-Modified は変更されません。 周期的な変化。このリソースがサイクル内で元の状態に変更された場合、キャッシュできると考えられますが、Last-Modified はキャッシュできるとは考えないため、ETag が存在します。
ETag/If-None-Match-
は Last-Modify/If-Modify-Since とは異なります。 Etag/If-None-Match はチェック コードを返します。 ETag は各リソースが一意であることを保証でき、リソースが変更されると ETag も変更されます。サーバーは、ブラウザーから送信された If-None-Match 値に基づいてキャッシュがヒットしたかどうかを判断します。
Last-Modified との違いは、サーバーが 304 Not Modified 応答を返すと、ETag が再生成されているため、ETag が以前の状態から変更されていない場合でも、ETag が応答ヘッダーで返されることです。前回のもの。
Last-Modified と ETag は併用できます。サーバーは最初に ETag を検証します。一貫性がある場合は、Last-Modified の比較を続け、最終的に 304 を返すかどうかを決定します。
#概要
ブラウザがすでにアクセスしているリソースにアクセスするときの手順は次のとおりです。
1. まず、強力なキャッシュがヒットするかどうかを確認します。ヒットした場合は、キャッシュを直接使用します。2. 強力なキャッシュがヒットしない場合は、確認するためにサーバーにリクエストが送信されます。ヒットしたら? ネゴシエート キャッシュ
3. ネゴシエーション キャッシュがヒットした場合、サーバーは 304 を返し、ローカル キャッシュが使用できることをブラウザに伝えます
4. ネゴシエーション キャッシュがヒットした場合、サーバーはブラウザに 304 を返します。ヒットしない場合、サーバーは新しいリソースをブラウザに返します
13.什么是浏览器的同源策略,以及跨域?
同源策略
同源策略是浏览器的一种自我保护行为。所谓的同源指的是:协议,域名,端口均要相同
浏览器中大部分内容都是受同源策略限制的,但是以下三个标签不受限制:
<img src="..." / alt="これらのブラウザ インタビューの質問を見てください。何問正しく答えることができますか?" >
<link href="..." />
<script src="..."></script>
跨域
跨域指的是浏览器不能执行其它域名下的脚本。它是由浏览器的同源策略限制的。
你可能会想跨域请求到底有没有发送到服务器?
事实上,跨域请求时能够发送到服务器的,并且服务器也能过接受的请求并正常返回结果,只是结果被浏览器拦截了。
跨域解决方案(列出几个常用的)
它主要是利用script标签不受浏览器同源策略的限制,可以拿到从其他源传输过来的数据,需要服务端支持。
优缺点:
兼容性比较好,可用于解决主流浏览器的跨域数据访问的问题。缺点就是仅支持get请求,具有局限性,不安全,可能会受到XSS攻击。
思路:
- 声明一个回调函数,其函数名(如show)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。
- 创建一个
<script></script>
标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=show)。
- 服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是show,它准备好的数据是
show('南玖')
。
- 最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(show),对返回的数据进行操作。
// front
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) => {
let script = document.createElement('script')
window[callback] = function(data) {
resolve(data)
document.body.removeChild(script)
}
params = { ...params, callback } // wd=b&callback=show
let arrs = []
for (let key in params) {
arrs.push(`${key}=${params[key]}`)
}
script.src = `${url}?${arrs.join('&')}`
document.body.appendChild(script)
})
}
jsonp({
url: 'http://localhost:3000/say',
params: { wd: 'wxgongzhonghao' },
callback: 'show'
}).then(data => {
console.log(data)
})
// server 借助express框架
let express = require('express')
let app = express()
app.get('/say', function(req, res) {
let { wd, callback } = req.query
console.log(wd) // Iloveyou
console.log(callback) // show
res.end(`${callback}('关注前端南玖')`)
})
app.listen(3000)
上面这段代码相当于向http://localhost:3000/say?wd=wxgongzhonghao&callback=show
这个地址请求数据,然后后台返回show('关注前端南玖')
,最后会运行show()这个函数,打印出'关注前端南玖'
CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。
服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
虽然设置 CORS 和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。
简单请求: (满足以下两个条件,就是简单请求)
1.请求方法为以下三个之一:
2.Content-Type的为以下三个之一:
- text-plain
- multiparty/form-data
- application/x-www-form-urlencoded
复杂请求:
不是简单请求那它肯定就是复杂请求了。复杂请求的CORS请求,会在正式发起请求前,增加一次HTTP查询请求,称为预检 请求,该请求是option方法的,通过该请求来知道服务端是否允许该跨域请求。
Nginx反向代理
Nginx 反向代理的原理很简单,即所有客户端的请求都必须经过nginx处理,nginx作为代理服务器再将请求转发给后端,这样就规避了浏览器的同源策略。
14.说说什么是XSS攻击
什么是XSS?
XSS 全称是 Cross Site Scripting
,为了与css
区分开来,所以简称XSS
,中文叫作跨站脚本
XSS是指黑客往页面中注入恶意脚本,从而在用户浏览页面时利用恶意脚本对用户实施攻击的一种手段。
XSS能够做什么?
- 窃取Cookie
- 监听用户行为,比如输入账号密码后之间发给黑客服务器
- 在网页中生成浮窗广告
- 修改DOM伪造登入表单
XSS实现方式
- 存储型XSS攻击
- 反射型XSS攻击
- 基于DOM的XSS攻击
如何阻止XSS攻击?
对输入脚本进行过滤或转码
对用户输入的信息过滤或者转码,保证用户输入的内容不能在HTML解析的时候执行。
利用CSP
该安全策略的实现基于一个称作 Content-Security-Policy
的HTTP首部。(浏览器内容安全策略)它的核心思想就是服务器决定浏览器加载那些资源。
- 限制加载其他域下的资源文件,这样即使黑客插入了一个 JavaScript 文件,这个 JavaScript 文件也是无法被加载的;
- 禁止向第三方域提交数据,这样用户数据也不会外泄;
- 提供上报机制,能帮助我们及时发现 XSS 攻击。
- 禁止执行内联脚本和未授权的脚本;
利用 HttpOnly
由于很多 XSS 攻击都是来盗用 Cookie 的,因此还可以通过使用 HttpOnly 属性来保护我们 Cookie 的安全。这样子的话,JavaScript 便无法读取 Cookie 的值。这样也能很好的防范 XSS 攻击。
通常服务器可以将某些 Cookie 设置为 HttpOnly 标志,HttpOnly 是服务器通过 HTTP 响应头来设置的,下面是打开 Google 时,HTTP 响应头中的一段:
set-cookie: NID=189=M8l6-z41asXtm2uEwcOC5oh9djkffOMhWqQrlnCtOI; expires=Sat, 18-Apr-2020 06:52:22 GMT; path=/; domain=.google.com; HttpOnly
对于不受信任的输入,可以限制输入长度
15.说说什么是CSRF攻击?
什么是CSRF攻击?
CSRF 全称 Cross-site request forgery
,中文为跨站请求伪造 ,攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。 CSRF攻击就是黑客利用用户的登录状态,并通过第三方站点来干一些嘿嘿嘿的坏事。
几种常见的攻击类型
1.GET类型的CSRF
GET类型的CSRF非常简单,通常只需要一个HTTP请求:
<img src="http://bank.example/withdraw?amount=10000&for=hacker" alt="これらのブラウザ インタビューの質問を見てください。何問正しく答えることができますか?" >
在受害者访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker
发出一次HTTP请求。bank.example就会收到包含受害者登录信息的一次跨域请求。
2.POST类型的CSRF
这种类型的CSRF利用起来通常使用的是一个自动提交的表单,如:
<form action="http://bank.example/withdraw" method=POST>
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>
访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。
3.链接类型的CSRF
链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
重磅消息!!
<a/>
由于之前用户登录了信任的网站A,并且保存登录状态,只要用户主动访问上面的这个PHP页面,则表示攻击成功。
CSRF的特点
- 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
- 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
- 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
- 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
CSRF通常是跨域的,因为外域通常更容易被攻击者掌控。但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,而且这种攻击更加危险。
防护策略
ハッカーは被害者の cookie
を使用してサーバーの信頼を騙すことしかできませんが、ハッカーは **"cookie"** の取得に頼ることはできませんし、**"cookie" のコンテンツを見ることもできません。さらに、ブラウザの「同一生成元ポリシー」制限により、ハッカーはサーバーから返された結果を解析できません。
これは、保護したいオブジェクトはデータ変更を直接生成できるサービスであり、データを読み取るサービスの場合は CSRF を保護する必要がないことがわかります。保護の鍵は
「ハッカーが偽造できない情報をリクエストに含める」
独自の検出
ほとんどの CSRF はサードパーティの Web サイトからのものであるため、外部ドメイン (または信頼できないドメイン名) が当社にリクエストを送信することを直接禁止しています。 では、問題は、リクエストが外部ドメインからのものであるかどうかをどのように判断するかということです。 HTTP プロトコルでは、各非同期リクエストには、ソース ドメイン名をマークするために使用される 2 つのヘッダーが含まれます:
Origin Header- Referer Header
-
これら 2 つのヘッダーは、ほとんどの場合、ブラウザーがリクエストを開始するときに自動的に取り込まれ、フロントエンドでコンテンツをカスタマイズすることはできません。サーバーは、これら 2 つのヘッダー内のドメイン名を解析することで、リクエストのソース ドメインを判断できます。
Origin ヘッダーを使用してソース ドメイン名を決定する
一部の CSRF 関連のリクエストでは、Origin フィールドがリクエストされたヘッダーに含まれます。このフィールドには、要求されたドメイン名 (パスとクエリを除く) が含まれます。 Origin が存在する場合は、Origin のフィールドを使用してソース ドメイン名を確認するだけです。 ただし、次の 2 つのケースでは、オリジンは存在しません:
- IE11 同一オリジン ポリシー: IE 11 は、クロスサイト CORS リクエスト ヘッダーにオリジンを追加しませんの場合でも、Referer ヘッダーが唯一の識別子になります。最も根本的な理由は、IE 11 の同一オリジンの定義が他のブラウザーと異なることです。主な違いは 2 つあります。MDN Same-origin_policy#IE_Exceptions
302 リダイレクトを参照してください。 : - オリジンは、他のソースからの機密情報とみなされる可能性があるため、302 リダイレクト後のリダイレクトされたリクエストには含まれません。 302 リダイレクトの場合、URL は新しいサーバーにダイレクトされるため、ブラウザはオリジンを新しいサーバーに漏洩することを望みません。
リファラー ヘッダーを使用してソース ドメイン名を決定するHTTP プロトコルによると、HTTP ヘッダーにはリファラーと呼ばれるフィールドがあり、 HTTPリクエストの送信元アドレス。 Ajax リクエスト、画像やスクリプトなどのリソース リクエストの場合、リファラーはリクエストを開始するページ アドレスです。ページ ジャンプの場合、Referer はページ履歴を開いた前のページのアドレスです。したがって、Referer 内のリンクの Origin 部分を使用して、リクエストのソース ドメイン名を知ることができます。
このメソッドは確実ではありません。Referer の値はブラウザによって提供されます。HTTP プロトコルには明確な要件がありますが、ブラウザごとに Referer の実装が異なる可能性があり、ブラウザが適切に実装するという保証はありません。独自のセキュリティホールはありません。 Referer 値を検証する方法は、セキュリティを確保するためにサードパーティ (ブラウザなど) に依存するため、理論的にはあまり安全ではありません。場合によっては、攻撃者は要求したリファラーを非表示にしたり、変更したりする可能性があります。
2014 年、W3C の Web アプリケーション セキュリティ ワーキング グループは、ブラウザがリファラーを送信する方法について詳細な規定を定めたリファラー ポリシーの草案をリリースしました。現時点では、ほとんどの新しいブラウザーがこのドラフトをサポートしており、最終的に Web サイトのリファラー戦略を柔軟に制御できるようになりました。新しいバージョンのリファラー ポリシーでは、リファラーなし、ダウングレード時リファラーなし、オリジンのみ、クロスオリジン時のオリジン、および安全でない URL の 5 つのリファラー ポリシーが規定されています。既存の 3 つの戦略 (never、default、always) は、新しい標準では名前が変更されました。対応関係は次のとおりです。
#ポリシー名属性値(新) | 属性値(旧) |
|
リファラーなし
no-Referrer | 決してしない |
| ダウングレード時にリファラーなし
no-Referrer-when-downgrade | default |
| Origin Only
(同じまたは厳密)origin | origin |
#Origin When Cross Origin |
(厳密)origin-when-crossorigin
- |
|
安全でないURL |
安全でない URL
常に |
| ##根据上面的表格因此需要把Referrer Policy的策略设置成same-origin,对于同源的链接和引用,会发送Referer,referer值为Host不带Path;跨域访问则不携带Referer。例如:aaa.com
引用bbb.com
的资源,不会发送Referer。
设置Referrer Policy的方法有三种:
在CSP设置
页面头部增加meta标签
a标签增加referrerpolicy属性
上面说的这些比较多,但我们可以知道一个问题:攻击者可以在自己的请求中隐藏Referer。如果攻击者将自己的请求这样填写:
<img src="http://bank.example/withdraw?amount=10000&for=hacker" referrerpolicy="no-referrer" alt="これらのブラウザ インタビューの質問を見てください。何問正しく答えることができますか?" >
那么这个请求发起的攻击将不携带Referer。
另外在以下情况下Referer没有或者不可信:
1.IE6、7下使用window.location.href=url进行界面的跳转,会丢失Referer。
2.IE6、7下使用window.open,也会缺失Referer。
3.HTTPS页面跳转到HTTP页面,所有浏览器Referer都丢失。
4.点击Flash上到达另外一个网站的时候,Referer的情况就比较杂乱,不太可信。
无法确认来源域名情况
当Origin和Referer头文件不存在时该怎么办?如果Origin和Referer都不存在,建议直接进行阻止,特别是如果您没有使用随机CSRF Token(参考下方)作为第二次检查。
如何阻止外域请求
通过Header的验证,我们可以知道发起请求的来源域名,这些来源域名可能是网站本域,或者子域名,或者有授权的第三方域名,又或者来自不可信的未知域名。
我们已经知道了请求域名是否是来自不可信的域名,我们直接阻止掉这些的请求,就能防御CSRF攻击了吗?
且慢!当一个请求是页面请求(比如网站的主页),而来源是搜索引擎的链接(例如百度的搜索结果),也会被当成疑似CSRF攻击。所以在判断的时候需要过滤掉页面请求情况,通常Header符合以下情况:
Accept: text/html
Method: GET
但相应的,页面请求就暴露在了CSRF的攻击范围之中。如果你的网站中,在页面的GET请求中对当前用户做了什么操作的话,防范就失效了。
例如,下面的页面请求:
GET https://example.com/addComment?comment=XXX&dest=orderId
注:这种严格来说并不一定存在CSRF攻击的风险,但仍然有很多网站经常把主文档GET请求挂上参数来实现产品功能,但是这样做对于自身来说是存在安全风险的。
另外,前面说过,CSRF大多数情况下来自第三方域名,但并不能排除本域发起。如果攻击者有权限在本域发布评论(含链接、图片等,统称UGC),那么它可以直接在本域发起攻击,这种情况下同源策略无法达到防护的作用。
综上所述:同源验证是一个相对简单的防范方法,能够防范绝大多数的CSRF攻击。但这并不是万无一失的,对于安全性要求较高,或者有较多用户输入内容的网站,我们就要对关键的接口做额外的防护措施。
CSRF Token
前面讲到CSRF的另一个特征是,攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。
而CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开,也可以防范CSRF的攻击。
利用Cookie的SameSite属性
可以看看MDN对此的解释:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie/SameSite
SameSite
可以设置为三个值,Strict
、Lax
和None
。
在Strict
模式下,浏览器完全禁止第三方请求携带Cookie。比如请求sanyuan.com
网站只能在sanyuan.com
域名当中请求才能携带 Cookie,在其他网站请求都不能。
在Lax
模式,就宽松一点了,但是只能在 get 方法提交表单
况或者a 标签发送 get 请求
的情况下可以携带 Cookie,其他情况均不能。
在None模式下,Cookie将在所有上下文中发送,即允许跨域发送。
更多编程相关知识,请访问:编程入门!!