>웹 프론트엔드 >프런트엔드 Q&A >이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?

이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?

青灯夜游
青灯夜游앞으로
2022-03-23 10:39:593719검색

이 기사에서는 브라우저에 관한 몇 가지 인터뷰 질문을 공유할 것입니다. 당신이 대답할 수 있는 질문은 몇 가지입니까? 정답을 분석하고 몇 개나 맞힐 수 있는지 확인해 보세요!

이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?

1. 일반적인 브라우저 커널은 무엇입니까?

브라우저 커널은 두 부분으로 나눌 수 있습니다:

渲染引擎JS引擎 (참고: 우리가 자주 참조하는 브라우저 커널은 렌더링 엔진을 의미합니다)

JS 엔진이 점점 더 발전하고 있기 때문에 독립적으로, 커널은 단지 렌더링 엔진을 의미하며 렌더링 엔진은 주로 네트워크 페이지 리소스를 구문 분석하고 조판하여 사용자에게 표시하도록 요청하는 데 사용됩니다

Browser/RunTime Kernel(렌더링 엔진) JavaScript 엔진
Chrome Blink(28~) 웹킷(Chrome 27) V8
FireFox Gecko SpiderMonkey
S afari Webkit JavaScriptCore
Edge EdgeHTML Chakra(JavaScript용)
IE Trident Chakra(JScript용)
Opera Presto->blink Linear A(4.0-6.1)/Line 아르 B(7.0 -9.2)/Futhark(9.5-10.2)/Carakan(10.5-)
Node.js - V8

2. 브라우저의 주요 구성요소는 무엇인가요?

  • 사용자 인터페이스: 주소 표시줄, 앞으로/뒤로/새로 고침/북마크 버튼 등 포함

  • 브라우저 엔진: 사용자 인터페이스와 렌더링 엔진 간에 명령을 전송합니다.

  • 렌더링 엔진: 요청을 그리는 데 사용됩니다.

  • 네트워크: http 요청과 같은 네트워크 호출을 완료하는 데 사용되며 플랫폼 독립적인 인터페이스를 가지며 다양한 플랫폼에서 작동할 수 있습니다.

  • JavaScript 인터프리터: JavaScript 코드를 구문 분석하고 실행하는 데 사용됩니다

  • 사용자 인터페이스 백엔드: 콤보박스, 윈도우 등 기본 위젯을 그리는 데 사용됩니다. 하단 레이어는 운영체제의 사용자 인터페이스를 사용합니다

  • 데이터 저장: 브라우저는 쿠키와 같은 다양한 데이터를 하드에 저장합니다. disk, HTML5는 가볍고 완전한 클라이언트측 저장 기술인 웹 데이터베이스 기술을 정의합니다

참고: 대부분의 브라우저와 달리 Google(Chrome) 브라우저의 각 탭은 각각 렌더링 엔진 인스턴스에 해당합니다. 각 탭은 독립적인 프로세스입니다

이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?

3. URL을 입력하면 페이지 렌더링이 어떻게 되는지 알려주세요.

이 질문은 면접에서 가장 많이 나오는 질문이라고 할 수 있고, 한없이 어려울 수 있습니다. 일반적으로 면접관들은 프론트엔드 지식의 깊이를 테스트하기 위해 이 질문을 합니다.

1. 브라우저는 URL을 수락하고 네트워크 요청 스레드를 엽니다(포함: 브라우저 메커니즘, 스레드 및 프로세스 등)

2 네트워크 스레드를 열고 완전한 http 요청을 발행합니다(포함: DNS 쿼리, TCP /IP 요청, 5계층 네트워크 프로토콜 등)

3. 서버에서 해당 백엔드로의 요청을 수신합니다. (관련: 로드 밸런싱, 보안 차단, 백엔드 내부 처리 등)

4. 백엔드 및 프런트엔드(대상: http 헤더, 응답 코드, 메시지 구조, 쿠키 등 포함)

5. 캐시 문제(관련: http 강력한 캐시 및 협상된 캐시, 캐시 헤더, etag, 만료, 캐시 제어, 등)

6. 브라우저 http 패킷을 수신한 후 구문 분석 프로세스(HTML 어휘 분석 포함, DOM 트리로 구문 분석, CSS를 구문 분석하여 CSSOM 트리 생성, 병합하여 렌더링 트리 생성) 복합 레이어 합성, GPU 드로잉, 외부 링크 처리 등)

7. CSS 시각적 모델(포함: 요소 렌더링 규칙, 예: 포함 블록, 컨트롤 박스, IFC 등)

8. 파싱 ​​프로세스(포함: JS 파싱 단계, 전처리 단계, 실행 단계는 실행 컨텍스트, VO(전역 객체), 범위 체인, 재활용 메커니즘 등을 생성합니다.) 입력 URL과 페이지 렌더링이 즉시 중단되었다고 느끼십니까? (걱정하지 마세요. 이 장에서는 이에 대해 자세히 다루지 않습니다. 먼저 이 질문에 대답하는 방법을 가르쳐 드리겠습니다. 나중에 별도의 기사에서 다룹니다.)

브라우저는 DNS 서버를 통해 도메인 이름의 IP 주소를 가져오고 이 IP 주소로 요청을 보냅니다. HTML 텍스트를 가져오기 위한 요청

    브라우저 렌더링 프로세스는 HTML 텍스트를 구문 분석하고 DOM 트리를 구축합니다
  • HTML을 구문 분석하는 동안 인라인 스타일이나 스타일 파일을 발견하면 스타일 규칙을 다운로드하고 JavaScript 스크립트를 발견하면 DOM을 실행합니다. 트리와 CSSOM이 구성되면 렌더링 프로세스는 둘을 렌더 트리로 병합합니다.
  • 렌더링 프로세스는 렌더링 트리를 레이아웃하고 레이아웃 트리를 생성하기 시작합니다.
  • 렌더 트리 대 레이아웃 트리 그리기 수행 및 그리기 기록 생성
  • 4. 브라우저는 코드를 어떻게 구문 분석하나요?

이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?

Parse HTML

HTML은 한 줄씩 구문 분석되며, 브라우저의 렌더링 엔진은 HTML 문서를 구문 분석하고 DOM 노드로 변환합니다. HTML을 여러 토큰으로 구문 분석

토큰을 객체로 구문 분석

    객체를 DOM 트리로 결합
  • CSS 구문 분석

브라우저는 CSS 선택기를 오른쪽에서 왼쪽으로 구문 분석합니다

그거 알아 DOM 트리와 CSSOM 트리는 렌더링 트리에 병합되어 실제로 CSSOM을 DOM 트리에 연결하므로 선택기가 제공하는 정보를 기반으로 DOM 트리를 탐색해야 합니다.

예를 살펴보겠습니다.

<style>
.nav .title span {color:blue}
</style>

<div class=&#39;nav&#39;>
  <div class=&#39;title&#39;>
    <span>南玖</span>
  </div>
  <div class="sub_title">前端</header>
</div>

오른쪽에서 왼쪽으로 일치:

먼저 가장 오른쪽에 있는 노드 범위를 모두 찾고, 각 범위에 대해 위쪽으로 노드 div.title

  • 을 검색합니다. 그런 다음 위쪽으로 div.nav의 노드

  • 가 마침내 루트 요소 html을 찾으면 이 분기의 순회가 종료됩니다.

  • Parse JS

브라우저에는 js 코드를 파싱하는 데 특별히 사용되는 js 파서 도구가 있습니다. 브라우저가 js 코드를 발견하면 즉시 "js 파서"를 호출하여 작동합니다.

파서는 js에서 모든 변수, 함수, 매개변수 등을 찾아 해당 변수 값을 정의되지 않음으로 할당합니다.

기능을 펑션블록에 꺼내어 창고에 보관하세요. 이 작업이 완료되면 코드는 한 줄씩(위에서 아래로, 왼쪽에서 오른쪽으로) 구문 분석되기 시작하고 창고와 일치됩니다.

5.DOMContentLoaded와 로드의 차이점은 무엇인가요?

  • DOMContentLoaded: 스타일 시트, 이미지 및 기타 리소스를 제외하고 DOM 구문 분석이 완료된 후에만 트리거됩니다.
  • 로드: 페이지의 모든 DOM, 스타일 시트, 스크립트, 이미지 및 기타 리소스가 로드되면 트리거됩니다.

6. 브라우저 다시 그리기와 도메인 재배치의 차이점은 무엇인가요?

  • 재배열: 렌더링 트리의 일부 또는 전체 렌더링 트리를 다시 분석하고 노드 크기를 다시 계산해야 하며, 이는 레이아웃을 재생성하고 요소를 재배열하는 것으로 나타납니다.
  • 다시 그리기: 노드의 기하학적 속성 또는 스타일 요소 배경 요소와 같은 변경 사항은 특정 요소의 모양이 변경되는 것으로 나타납니다.

다시 그리는 것이 반드시 리플로우로 이어지는 것은 아니지만 다시 그리면 확실히 다시 그리기로 이어집니다

방법 다시 그리기 및 리플로우를 트리거합니까?

렌더 트리를 구축하는 데 사용된 정보를 변경하면 리플로우 또는 다시 그리기가 발생합니다.

  • DOM 노드 추가, 삭제, 업데이트
  • 디스플레이를 통해 DOM 노드 숨기기: 없음 - 리플로우 및 다시 그리기 트리거
  • 가시성을 통해 DOM 노드 숨기기: 숨김 - 기하학적 변경 사항이 없으므로 다시 그리기만 트리거합니다.
  • 페이지에서 DOM 노드를 이동하거나 애니메이션화합니다.
  • 스타일시트 추가 및 스타일 속성 조정
  • 창 크기 조정과 같은 사용자 동작, 글꼴 크기를 변경하거나 스크롤합니다.

다시 그리거나 리플로우하는 것을 방지하는 방법은 무엇입니까?

  • 스타일 집중 변경: 예를 들어 클래스를 사용하여 스타일을 일괄적으로 변경합니다.

  • document.createDocumentFragment() 사용: DOM 트리에서 자유로운 문서를 생성할 수 있습니다. createDocumentFragment 노드를 통해 이 노드에서 일괄 작업이 수행되고 마지막으로 DOM 트리에 삽입되므로 한 번의 리플로우만 트리거됩니다. document.createDocumentFragment():我们可以通过createDocumentFragment创建一个游离于DOM树之外的节点,然后在此节点上批量操作,最后插入DOM树中,因此只触发一次重排

  • 提升为合成层

    将元素提升为合成层有以下优点:

    • 合成层的位图,会交由 GPU 合成,比 CPU 处理要快

    • 当需要repaint 时,只需要 repaint 本身,不会影响到其他的层

    • 对于 transformopacity 效果,不会触发 layoutpaint

      提升合成层的最好方式是使用 CSS 的 will-change 属性

7.为什么JS是单线程的?

这主要与JS的用途有关,JS作为浏览器的脚本语言,最初主要是实现用户与浏览器的交互,以及操作DOM。这就决定了它只能是单线程,否则会带来许多复杂的同步问题。

举个例子: 如果JS是多线程的,其中一个线程要修改一个DOM元素,另外一个线程想要删除这个DOM元素,这时候浏览器就不知道该听谁的。所以为了避免复杂性,从一诞生,JavaScript就被设计成单线程。

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质

8.CSS加载会阻塞DOM吗?

先上结论

  • CSS不会阻塞DOM的解析,但会阻塞DOM的渲染
  • CSS会阻塞JS执行,但不会阻塞JS文件的下载

CSSOM的作用

  • 第一个是提供给JavaScript操作样式表的能力

  • 第二个是为布局树的合成提供基础的样式信息

  • 这个CSSOM体现在DOM中就是document.styleSheets

컴포지션 레이어로 승격

요소를 컴포지션 레이어로 승격하면 다음과 같은 장점이 있습니다.
  • 컴포지션 레이어의 비트 이미지는 CPU 처리보다 빠른 GPU로 합성됩니다

  • 다시 칠하기할 때 >가 필요하며 다시 그리기 자체만 다른 레이어에 영향을 주지 않습니다

    변형불투명도 효과의 경우 레이아웃 code> 및 <code will not be triggered>paint
  • 컴포지션 레이어를 향상하는 가장 좋은 방법은 CSS will-change 속성

  • 7. JS는 왜 단일 스레드인가요?

이것은 주로 JS의 목적과 관련이 있습니다. 브라우저의 스크립트 언어로서 JS는 처음에는 사용자와 브라우저 간의 상호 작용을 구현하고 DOM을 운영하는 데 주로 사용되었습니다. 이는 단일 스레드만 가능하다는 것을 결정합니다. 그렇지 않으면 많은 복잡한 동기화 문제가 발생합니다. 예: JS가 다중 스레드인 경우 한 스레드는 DOM 요소를 수정하려고 하고 다른 스레드는 DOM 요소를 삭제하려고 하면 브라우저는 누구의 말을 들어야 할지 알 수 없습니다. 따라서 복잡성을 피하기 위해 JavaScript는 처음부터 단일 스레드로 설계되었습니다.

🎜🎜멀티 코어 CPU의 컴퓨팅 성능을 활용하기 위해 HTML5는 JavaScript 스크립트가 여러 스레드를 생성할 수 있도록 허용하지만 하위 스레드는 메인 스레드에 의해 완전히 제어되며 스레드를 작동해서는 안 되는 Web Worker 표준을 제안합니다. DOM. 따라서 이 새로운 표준은 JavaScript🎜🎜

의 단일 스레드 특성을 변경하지 않습니다. 8. CSS 로딩이 DOM을 차단합니까? 🎜🎜🎜🎜먼저 결론🎜🎜🎜
🎜🎜CSSDOM의 구문 분석을 차단하지 않지만 DOM 🎜🎜<code>CSSJS의 실행을 차단하지만 JS 파일🎜🎜
🎜의 다운로드는 차단하지 않습니다. 🎜🎜CSSOM의 역할🎜 🎜🎜🎜🎜🎜첫 번째는 JavaScript에 스타일 시트를 조작할 수 있는 기능을 제공하는 것입니다.🎜🎜🎜🎜두 번째는 레이아웃 트리 합성을 위한 기본 스타일 정보를 제공하는 것입니다🎜🎜🎜🎜이 CSSOM은 DOM에 document .styleSheets🎜🎜🎜🎜로 반영됨 앞서 언급한 브라우저 렌더링 프로세스에서 볼 수 있습니다. 🎜🎜🎜🎜DOM과 CSSOM은 일반적으로 병렬로 구축되므로 🎜CSS 로딩이 차단되지 않습니다. DOM 구문 분석🎜🎜🎜 🎜🎜렌더 트리는 DOM 트리와 CSSOM 트리에 따라 다르므로 둘 다 로드될 때까지 기다려야 렌더링 작성을 시작할 수 있으므로 🎜CSS 로드로 인해 DOM 렌더링이 차단됩니다🎜🎜🎜🎜🎜 JavaScript는 DOM과 CSS를 동작시킬 수 있기 때문에, 이들 요소의 속성을 수정하면서 인터페이스를 렌더링한다면(즉, JavaScript 스레드와 UI 스레드가 동시에 수행되는 경우), 렌더링 스레드 이전과 이후에 얻은 요소는 다음과 같을 수 있습니다. 일관성 없는. 따라서 예상치 못한 렌더링 결과를 방지하기 위해 브라우저는 🎜GUI 렌더링 스레드와 JavaScript 스레드를 상호 배타적으로 설정합니다🎜🎜🎜🎜🎜🎜🎜JS는 CSS 다운로드를 기다려야 합니다. 이유는 무엇입니까? (CSS는 DOM 실행을 차단합니다)🎜🎜🎜

JS 스크립트의 내용이 요소의 스타일을 가져오는 것이라면 CSS를 사용해야 합니다. 브라우저는 JS 내부에서 무슨 일이 일어나고 있는지 감지할 수 없기 때문에 스타일 획득을 피하기 위해 JS를 실행하기 전에 이전 스타일이 모두 다운로드될 때까지 기다려야 합니다. 단, JS 파일과 CSS 파일은 병렬로 다운로드되어 후속 JS 파일이 실행되기 전에 CSS 파일이 로드되어 실행되므로 JS脚本的内容是获取元素的样式,那它就必然依赖CSS。因为浏览器无法感知JS内部到底想干什么,为避免样式获取,就只好等前面所有的样式下载完毕再执行JS。但JS文件与CSS文件下载是并行的,CSS文件会在后面的JS文件执行前先加载执行完毕,所以CSS会阻塞后面JS的执行

避免白屏,提高CSS的加载速度

  • 使用CDN(CDN会根据你的网络状况,挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
  • 对CSS进行压缩
  • 合理使用缓存
  • 减少http请求数,合并CSS文件

9.JS会阻塞页面吗?

先上结论

JS会阻塞DOM的解析,因此也就会阻塞页面的加载

这也是为什么我们常说要把JS文件放在最下面的原因

由于 JavaScript 是可操纵 DOM 的,如果在修改这些元素属性同时渲染界面(即 JavaScript 线程和 UI 线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。

因此为了防止渲染出现不可预期的结果,浏览器设置 **「GUI 渲染线程与 JavaScript 引擎为互斥」**的关系。

当 JavaScript 引擎执行时 GUI 线程会被挂起,GUI 更新会被保存在一个队列中等到引擎线程空闲时立即被执行。

当浏览器在执行 JavaScript 程序的时候,GUI 渲染线程会被保存在一个队列中,直到 JS 程序执行完成,才会接着执行。

因此如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

10.defer和async的区别?

  • 两者都是异步去加载外部JS文件,不会阻塞DOM解析
  • Async是在外部JS加载完成后,浏览器空闲时,Load事件触发前执行,标记为async的脚本并不保证按照指定他们的先后顺序执行,该属性对于内联脚本无作用 (即没有**「src」**属性的脚本)。
  • defer是在JS加载完成后,整个文档解析完成后,触发 DOMContentLoaded 事件前执行,如果缺少 srcCSS는 후속 JS 실행을 차단

화이트 스크린을 방지하고 개선합니다. CSS 로딩 속도

CDN 사용(CDN은 캐시된 콘텐츠가 있는 가장 가까운 노드를 선택하여 네트워크 상태에 따라 리소스를 제공하므로 로딩 시간을 줄일 수 있습니다.)

CSS 압축

캐시를 합리적으로 사용

http 요청 수 감소, CSS 파일 병합

9. JS가 페이지를 차단합니까?

먼저 결론을 내리자

JS는 DOM 파싱을 차단

하므로 페이지 로딩을 차단하게 됩니다

이래서 JS 파일을 맨 밑에 넣어야 한다는 이야기를 자주 하는 이유입니다.

JavaScript는 DOM을 조작할 수 있으므로 인터페이스를 렌더링하는 동안 이러한 요소의 속성을 수정하면(즉, JavaScript 스레드와 UI 스레드가 동시에 실행됨) 렌더링 스레드 전후에 얻은 요소 데이터가 일관성이 없을 수 있습니다.

따라서 예상치 못한 렌더링 결과를 방지하기 위해 브라우저는 **"GUI 렌더링 스레드와 JavaScript 엔진은 상호 배타적입니다"** 관계를 설정합니다.

JavaScript 엔진이 실행되면 GUI 스레드가 일시 중지되고 GUI 업데이트가 대기열에 저장되어 엔진 스레드가 유휴 상태가 되면 즉시 실행됩니다.

브라우저가 JavaScript 프로그램을 실행할 때 GUI 렌더링 스레드는 대기열에 저장되며 JS 프로그램이 완료될 때까지 실행되지 않습니다.

그래서 JS의 실행 시간이 너무 길면 페이지 렌더링이 일관되지 않아 페이지 렌더링 및 로딩이 차단되는 느낌을 받게 됩니다.

10. 지연과 비동기의 차이점은 무엇인가요?

둘 다 외부 JS 파일을 비동기식으로 로드하며 DOM 구문 분석을 차단하지 않습니다.
  • Async는 외부 JS 로드가 완료된 후, 브라우저가 유휴 상태일 때, Load 이벤트가 트리거되기 전에 실행됩니다. 실행되는 순서를 지정하십시오. 이 속성은 인라인 스크립트(즉, "src" 속성이 없는 스크립트)에는 영향을 미치지 않습니다.
  • defer는 JS가 로드된 후, 전체 문서가 구문 분석된 후, src 속성(예: 내장된 스크립트)이 트리거되기 전에 실행됩니다. 누락된 경우 이 속성은 작동하지 않으므로 사용하면 안 됩니다.
  • 11. 브라우저의 가비지 수집 메커니즘

가비지 수집은 자동 메모리 관리 메커니즘입니다. 컴퓨터의 동적 메모리는 더 이상 필요하지 않을 때 해제되어야 합니다.

자동이란 브라우저가 자동으로 메모리 쓰레기를 재활용하는 데 도움을 줄 수 있다는 의미이지만, 메모리 관리에 신경 쓸 필요가 없다는 의미는 아닙니다. 제대로 작동하지 않으면 JavaScript에서 메모리 오버플로가 계속 발생합니다. , 시스템 충돌을 일으킵니다. 🎜🎜🎜문자열, 배열, 객체 등은 고정된 크기가 없으므로 크기가 알려지면 동적으로 할당해야 합니다. JavaScript 프로그램이 문자열, 배열 또는 객체를 생성할 때마다 인터프리터는 해당 엔터티를 저장하기 위해 메모리를 할당해야 합니다. 🎜🎜JavaScript 해석기는 프로그램이 더 이상 객체를 사용하지 않는 시기를 감지할 수 있습니다. 객체가 쓸모없다고 판단되면 객체가 더 이상 필요하지 않다는 것을 알고 객체가 차지하는 메모리를 해제할 수 있습니다. 🎜🎜브라우저에서 일반적으로 사용하는 가비지 수집 방법에는 🎜마크 스윕🎜, 🎜참조 카운팅🎜이라는 두 가지 방법이 있습니다. 🎜🎜🎜🎜마크 지우기🎜🎜🎜🎜🎜이것은 JavaScript에서 가장 일반적으로 사용되는 가비지 수집 방법입니다.🎜🎜🎜2012년 이후 모든 최신 브라우저는 하위 버전의 IE 참조 카운팅을 제외하고 마크 지우기 가비지 수집 방법을 사용했습니다. 🎜🎜🎜그럼 마크제거란 무엇일까요? 🎜🎜🎜🎜JavaScript에는 전역 개체가 있습니다. 주기적으로 가비지 수집기는 이 전역 개체에서 시작하여 이 전역 개체에서 참조되는 모든 개체를 찾은 다음 이러한 개체가 참조하는 개체를 찾습니다. 이러한 활성 개체의 경우 마킹, 마킹 단계입니다. 지우기 단계는 표시되지 않은 개체를 지우는 것입니다. 🎜🎜🎜마크 클리어의 문제점은 클리어 후 메모리 공간이 불연속적, 즉 메모리 조각화가 발생한다는 것입니다. 나중에 상대적으로 큰 연속 메모리 공간이 필요할 경우 요구 사항을 충족하지 못합니다. 🎜마크 정리🎜 방법은 이 문제를 효과적으로 해결할 수 있습니다. 🎜🎜마킹 과정에서 3색 마킹 개념이 도입되었습니다. 3가지 색상은 🎜🎜🎜흰색: 표시되지 않은 개체, 즉 도달할 수 없는 개체(스캔되지 않은 개체)를 재활용할 수 있습니다. 🎜🎜회색. : 표시가 된 개체(접근 가능한 개체)이지만 아직 검사되지 않아 재활용할 수 없는 개체 🎜🎜검은색: 검사된(접근 가능한 개체)이며 재활용할 수 없는 개체 🎜🎜🎜🎜 표시 정렬: 🎜🎜

마킹 단계는 마킹이 완료된 후 살아남은 개체를 메모리의 한쪽으로 이동하고 마지막으로 경계 메모리를 정리한다는 점을 제외하면 마크 앤 클리어 방법과 다르지 않습니다.

참조 카운팅

참조 카운팅의 의미는 각 값이 참조되는 횟수를 추적하는 것입니다. 변수 A에 값이 할당되면 이 값에 대한 참조 수는 1입니다. 변수 A가 다시 할당되면 이전 값에 대한 참조 수가 1씩 줄어듭니다. 참조 개수가 0이 되면 더 이상 이 값에 접근할 수 없다는 뜻이므로 이 값이 차지하는 메모리를 지울 수 있다.

대부분의 브라우저는 이 재활용 방법을 포기했습니다.

메모리 누수

메모리 누수를 방지하려면 데이터가 더 이상 사용되지 않으면 해당 값을 null로 설정하는 것이 가장 좋습니다. code>참조를 해제하려면 이 방법을 null来释放其引用,这个方法叫做接触引用

哪些情况会造成内存泄漏?如何避免?

以 Vue 为例,通常有这些情况:

  • 监听在 window/body 等事件没有解绑
  • 绑在 EventBus 的事件没有解绑
  • Vuex$storewatch 了之后没有 unwatch
  • 使用第三方库创建,没有调用正确的销毁函数

解决办法:beforeDestroy 中及时销毁

  • 绑定了 DOM/BOM 对象中的事件 addEventListenerremoveEventListener
  • 观察者模式 $on$off处理。
  • 如果组件中使用了定时器,应销毁处理。
  • 如果在 mounted/created 钩子中使用了第三方库初始化,对应的销毁。
  • 使用弱引用 weakMapweakSet

浏览器中不同类型变量的内存都是何时释放的?

  • 引用类型

    • 在没有引用之后,通过 V8 自动回收。
  • 基本类型

    • 如果处于闭包的情况下,要等闭包没有引用才会被 V8 回收。
    • 非闭包的情况下,等待 V8 的新生代切换的时候回收。

12.说一说浏览器的缓存机制?

认识浏览器缓存

当浏览器请求一个网站时,会加载各种资源,对于一些不经常变动的资源,浏览器会将他们保存在本地内存中,下次访问时直接加载这些资源,提高访问速度。

如何知道资源是请求的服务器还是读取的缓存呢?

이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?

看上面这张图,有些资源的size值是大小,有些是from disk cache,有些是from memory cache,显示大小的是请求的服务器资源,而显示后面两种的则是读取的缓存。

  • disk cache: 就是将资源存储在磁盘中,等待下次访问时不需重新下载,直接从磁盘中读取,它的直接操作对象为CurlCacheManagerContact reference
  • 어떤 상황에서 메모리 누수가 발생하나요? 그것을 피하는 방법?
Vue를 예로 들면 일반적으로 다음과 같은 상황이 있습니다.
해결책: beforeDestroy
DOM/BOM에서 <code>addEventListener 개체 /code>, <code>removeEventListener. 관찰자 모드 $on, $off 처리. 컴포넌트에 타이머가 사용된 경우 해당 컴포넌트를 파기해야 합니다. 마운트/생성 후크에서 타사 라이브러리 초기화가 사용되는 경우 그에 따라 삭제됩니다. 약한 참조 weakMap, weakSet을 사용하세요. 브라우저의 다양한 변수 유형에 대한 메모리는 언제 출시되나요?
    참조 유형은 참조가 없으면 V8에서 자동으로 재활용됩니다. 기본 유형
      window/body에서 모니터링되는 이벤트는 바인딩 해제되지 않습니다. EventBus에 바인딩된 이벤트는 바인딩 해제되지 않음 Vuex$store 바인딩을 해제한 후 watch는 타사 라이브러리가 호출되지 않습니다.
        클로저에 있는 경우 클로저에 참조가 없을 때까지 V8에서 재활용되지 않습니다. 🎜🎜비밀폐형의 경우 V8의 차세대 스위치를 기다리며 재활용됩니다. 🎜🎜🎜🎜

        12. 브라우저의 캐싱 메커니즘에 대해 알려주세요.

        🎜🎜🎜브라우저 캐시 이해하기🎜🎜🎜🎜브라우저가 웹사이트를 요청할 때 다양한 리소스를 로드합니다. 자주 변경되지 않는 일부 리소스의 경우 브라우저는 다음 번에 이를 위해 로컬 메모리에 저장합니다. 액세스 속도를 향상시키기 위해 액세스 중에 직접. 🎜🎜🎜🎜리소스가 서버에서 요청되었는지 아니면 캐시에서 읽혀졌는지 어떻게 알 수 있나요? 🎜🎜🎜🎜이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?🎜 🎜위 그림을 보세요. 일부 리소스의 크기 값은 디스크 캐시에서이고, 일부는 메모리 캐시에서입니다. 요청된 서버 리소스 중 두 개는 읽기 캐시로 표시됩니다. 🎜
          🎜🎜디스크 캐시: 🎜 디스크에 리소스를 저장하고 다시 다운로드하지 않고 다음 액세스를 기다리는 것입니다. 디스크에서 직접 읽을 수 있습니다. CurlCacheManager . (메모리캐시에 비해 효율은 느리지만 저장용량이 크고 저장시간이 길다) 🎜🎜🎜메모리캐시 : 🎜 메모리에 자원을 캐싱하고, 재다운로드 없이 다음 접근을 기다리는 것이며, 메모리에서 직접 읽기. (효율성 측면에서 가장 빠르며, 생존 시점 측면에서 가장 짧습니다.) 🎜🎜🎜🎜🎜🎜-🎜🎜메모리 캐시🎜🎜디스크 캐시🎜🎜🎜🎜🎜🎜동일 포인트🎜🎜 가능 일부 파생 리소스 파일만 저장🎜🎜일부 파생 리소스 파일만 저장할 수 있습니다🎜🎜🎜🎜차이점🎜🎜프로세스를 종료하면 데이터가 지워집니다🎜🎜프로세스를 종료해도 데이터는 지워지지 않습니다🎜🎜🎜🎜저장 resources🎜🎜일반 스크립트, 글꼴, 그림은 메모리에 저장됩니다. 일반적으로 CSS 등 비스크립트는 메모리에 저장됩니다.

          브라우저 캐시 분류

          • 강한 캐시
          • 협상 캐시

          브라우저는 서버에 리소스를 요청할 때 먼저 Strong 캐시에 도달했는지 확인하고, 실패하면 적중 여부를 확인합니다. 협상 캐시

          Strong Cache

          브라우저가 리소스를 로드할 때 먼저 로컬 캐시 리소스의 헤더를 기반으로 강력한 캐시에 도달했는지 여부를 결정합니다. , 캐시의 리소스가 직접 사용되며 서버가 요청을 다시 보내지 않습니다. header中判断是否命中强缓存,如果命中则直接使用缓存中的资源,不会再向服务器发送请求。 (这里的header中的信息指的是 expirescache-control

          • Expires

          该字段是 http1.0 时的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。所以这种方式很快在后来的HTTP1.1版本中被抛弃了。

          • Cache-Control

          Cache-Control 是 http1.1 时出现的 header 信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。cache-control 除了该字段外,还有下面几个比较常用的设置值:

          no-cache:需要进行协商缓存,发送请求到服务器确认是否使用缓存。

          no-store:禁止使用缓存,每一次都要重新请求数据。

          public:可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。

          private:只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。

          Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。

          协商缓存

          当强缓存没命中时,浏览器会发送一个请求到服务器,服务器根据 header 中的信息来判断是否命中协商缓存。如果命中,则返回304 ,告诉浏览器资源未更新,可以使用本地缓存。 (这里的header信息指的是Last-Modify/If-Modify-SinceETag/If-None-Match(여기 헤더의 정보는 expirescache-control을 참조합니다.)

          • Expires

          이 필드는

          http1.0

          입니다. 시간 지정의 경우 해당 값은 Expires:Mon,18 Oct 2066 23:59:59 GMT와 같은 GMT 형식의

          절대 시간

          시간 문자열입니다. 이 시간은 이 시간 이전에 캐시가 적중되는 시간을 나타냅니다. 이 방법은 만료 시간이 절대 시간이기 때문에 서버와 클라이언트 사이의 시간 편차가 클 경우 캐시 혼란이 발생한다는 명백한 단점이 있습니다. 따라서 이 방법은 이후 버전의 HTTP 1.1에서 빠르게 폐기되었습니다.

          Cache-Control

          • Cache-Control은 http1.1일 때 나타나는 헤더 정보로 주로 이 필드의

            max-age
          • 값을 사용하여 판단합니다. 상대 시간
          예를 들어 Cache-Control:max-age=3600은 리소스 유효 기간이 3600초임을 의미합니다. 이 필드 외에도 캐시 제어에는 일반적으로 사용되는 다음과 같은 설정 값도 있습니다.

          no-cache

          : 캐시를 협상하고 서버에 캐시 사용 여부를 확인하는 요청을 보내야 합니다.

          no-store

          : 캐싱을 비활성화하고 매번 데이터를 다시 요청합니다.

          public: 최종 사용자 및 CDN과 같은 중간 프록시 서버를 포함한 모든 사용자가 캐시할 수 있습니다.

          private: 최종 사용자의 브라우저에서만 캐시할 수 있으며 CDN과 같은 릴레이 캐시 서버에서는 캐시가 허용되지 않습니다.

          캐시 제어 및 만료는 서버 구성에서 동시에 활성화할 수 있습니다. 동시에 활성화하면 캐시 제어의 우선 순위가 높아집니다.

          협상 캐시

          🎜🎜강한 캐시가 누락되면 브라우저는 서버에 요청을 보내고 서버는 헤더의 정보를 기반으로 협상 캐시 적중 여부를 결정합니다. . 적중하면 🎜304🎜가 반환되어 리소스가 업데이트되지 않았으며 로컬 캐시를 사용할 수 있음을 브라우저에 알립니다. 🎜(여기서 헤더 정보는 Last-Modify/If-Modify-SinceETag/If-None-Match를 참조합니다.)🎜🎜🎜🎜🎜🎜Last-Modify / If-Modify-Since🎜🎜🎜🎜🎜브라우저가 처음으로 리소스를 요청할 때 서버가 반환한 헤더에 Last-Modify가 추가됩니다. Last-modify는 리소스의 마지막 수정 시간을 식별하는 시간입니다. . 🎜🎜브라우저가 리소스를 다시 요청하면 요청 헤더에는 캐싱 전에 반환된 Last-Modify인 If-Modify-Since가 포함됩니다. 서버는 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를 반환할지 결정합니다. 🎜🎜🎜🎜🎜Summary🎜🎜🎜🎜🎜브라우저가 이미 방문한 리소스에 액세스할 때 단계는 다음과 같습니다. 🎜🎜🎜1 먼저 강력한 캐시에 도달했는지 확인하세요. 캐시를 직접 사용하세요🎜🎜2. .강한 캐시에 도달하지 않으면 요청이 서버로 전송되어 협상 캐시에 도달했는지 확인합니다. 🎜🎜3. 협상 캐시에 도달하면 서버는 304를 반환하여 브라우저에 로컬 캐시가 있음을 알립니다. 4. 협상 캐시에 도달하지 않으면 서버는 새 리소스를 브라우저에 반환합니다🎜

          13.什么是浏览器的同源策略,以及跨域?

          同源策略

          同源策略是浏览器的一种自我保护行为。所谓的同源指的是:协议,域名,端口均要相同

          浏览器中大部分内容都是受同源策略限制的,但是以下三个标签不受限制:

          <img  src="..." / alt="이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?" >
          <link href="..." />
          <script src="..."></script>

          跨域

          跨域指的是浏览器不能执行其它域名下的脚本。它是由浏览器的同源策略限制的。

          你可能会想跨域请求到底有没有发送到服务器?

          事实上,跨域请求时能够发送到服务器的,并且服务器也能过接受的请求并正常返回结果,只是结果被浏览器拦截了。

          跨域解决方案(列出几个常用的)

          • JSONP

          它主要是利用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(&#39;script&#39;)
              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(&#39;&&#39;)}`
              document.body.appendChild(script)
            })
          }
          jsonp({
            url: &#39;http://localhost:3000/say&#39;,
            params: { wd: &#39;wxgongzhonghao&#39; },
            callback: &#39;show&#39;
          }).then(data => {
            console.log(data)
          })
          // server 借助express框架
          let express = require(&#39;express&#39;)
          let app = express()
          app.get(&#39;/say&#39;, function(req, res) {
            let { wd, callback } = req.query
            console.log(wd) // Iloveyou
            console.log(callback) // show
            res.end(`${callback}(&#39;关注前端南玖&#39;)`)
          })
          app.listen(3000)

          上面这段代码相当于向http://localhost:3000/say?wd=wxgongzhonghao&callback=show这个地址请求数据,然后后台返回show('关注前端南玖'),最后会运行show()这个函数,打印出'关注前端南玖'

          • 跨域资源共享(CORS)

          CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

          CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现

          浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。

          服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。

          虽然设置 CORS 和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求复杂请求

          简单请求: (满足以下两个条件,就是简单请求)

          1.请求方法为以下三个之一:

          • GET
          • POST
          • HEAD

          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 보호가 필요하지 않음을 알려줍니다. 보호의 핵심은

          "해커가 위조할 수 없는 정보를 요청에 넣는 것"입니다

          원본 탐지

          대부분의 CSRF는 타사 웹사이트에서 제공되므로 외부 도메인(또는 신뢰할 수 있는 도메인이 아님)을 직접 금지합니다. 이름) 우리에게 요청하십시오.

          그렇다면 질문은 요청이 외부 도메인에서 오는지 어떻게 판단할 수 있느냐는 것입니다.

            HTTP 프로토콜에서 각 비동기 요청에는 원본 도메인 이름을 표시하는 두 개의 헤더가 있습니다.
          • Origin Header
          Referer Header

          브라우저가 요청을 시작할 때 이 두 헤더는 대부분의 경우 자동으로 가져옵니다. 콘텐츠는 프런트 엔드에서 맞춤설정할 수 없습니다. 서버는 이 두 헤더의 도메인 이름을 구문 분석하여 요청의 소스 도메인을 결정할 수 있습니다.

          Origin 헤더를 사용하여 소스 도메인 이름을 결정하세요

          일부 CSRF 관련 요청에서는 Origin 필드가 요청된 헤더에 전달됩니다. 필드에는 요청된 도메인 이름(경로 및 쿼리 제외)이 포함됩니다.

          Origin이 존재하는 경우 Origin의 필드를 사용하여 원본 도메인 이름을 직접 확인할 수 있습니다.

            그러나 다음 두 가지 경우에는 Origin이 존재하지 않습니다.
          • IE11 동일한 Origin 정책: IE 11은 사이트 간 CORS 요청에 Origin 헤더를 추가하지 않으며 Referer 헤더는 여전히 고유 식별자입니다. 가장 근본적인 이유는 IE 11의 동일 출처에 대한 정의가 다른 브라우저와 다르기 때문입니다. 두 가지 주요 차이점은
          • MDN Same-origin_policy#IE_Exceptions
          • 302 리디렉션을 참조하세요.
          302 리디렉션 이후의 출처는 포함되지 않습니다. Origin으로 인해 리디렉션된 요청은 다른 소스의 민감한 정보로 간주될 수 있습니다. 302 리디렉션의 경우 URL이 새 서버로 연결되므로 브라우저는 원본을 새 서버로 유출하는 것을 원하지 않습니다.

          Referer 헤더를 사용하여 소스 도메인 이름 결정

          HTTP 프로토콜에 따르면 HTTP 헤더에는 HTTP 요청의 소스 주소를 기록하는 Referer라는 필드가 있습니다. Ajax 요청, 이미지 및 스크립트와 같은 리소스 요청의 경우 리퍼러는 요청을 시작하는 페이지 주소입니다. 페이지 점프의 경우 Referer는 페이지 기록을 연 이전 페이지의 주소입니다. 따라서 리퍼러 링크의 원본 부분을 사용하여 요청의 소스 도메인 이름을 알 수 있습니다.

          이 방법은 완벽하지 않습니다. HTTP 프로토콜에 대한 명확한 요구 사항이 있지만 각 브라우저에는 서로 다른 Referer 구현이 있을 수 있습니다. 브라우저 자체에 보안 취약점이 없다는 보장은 없습니다. . Referer 값을 확인하는 방법은 보안을 보장하기 위해 제3자(즉, 브라우저)에 의존합니다. 이는 이론적으로 그다지 안전하지 않습니다. 어떤 경우에는 공격자가 요청한 리퍼러를 숨기거나 수정할 수도 있습니다.

          2014년 W3C의 웹 애플리케이션 보안 실무 그룹은 브라우저가 리퍼러를 보내는 방법에 대한 자세한 조항을 담은 리퍼러 정책 초안을 발표했습니다. 현재 대부분의 새로운 브라우저는 이 초안을 지원하고 있으며 마침내 우리 웹사이트의 추천자 전략을 유연하게 제어할 수 있게 되었습니다. 새 버전의 리퍼러 정책은 리퍼러 없음, 다운그레이드 시 리퍼러 없음, 원본만, 원본 간 원본, 안전하지 않은 URL 등 5가지 리퍼러 정책을 규정합니다. 세 가지 기존 전략인 never, default 및 Always는 새 표준에서 이름이 변경되었습니다. 해당 대응은 다음과 같습니다. 속성 값(기존)never -안전하지 않은 URLunsafe-urlalways 다운로드

          根据上面的表格因此需要把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可以设置为三个值,StrictLaxNone

          • Strict模式下,浏览器完全禁止第三方请求携带Cookie。比如请求sanyuan.com网站只能在sanyuan.com域名当中请求才能携带 Cookie,在其他网站请求都不能。

          • Lax模式,就宽松一点了,但是只能在 get 方法提交表单况或者a 标签发送 get 请求的情况下可以携带 Cookie,其他情况均不能。

          • 在None模式下,Cookie将在所有上下文中发送,即允许跨域发送。

          更多编程相关知识,请访问:编程入门!!

          전략 이름 속성 값(신규)
          No Referrer no-Referrer
          추천인이 없는 경우

        위 내용은 이 브라우저 인터뷰 질문을 살펴보세요. 몇 개나 정답을 맞힐 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

        성명:
        이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제