sessionstorage 与localStorage之间的区别
sessionStorage和localStorage都是浏览器客户端存储数据的方式。
它们允许网站在用户的浏览器中存储键值对,
并且这些数据在页面重新加载后仍然可用。
会话是什么
会话(Session)是指在指定的时间段内,用户在浏览器(或APP、小程序等客户端)上与网站进行的一系列交互行为的集合
。简而言之,当用户打开一个浏览器窗口,开始访问某个网站,并在一段时间内与网站进行交互(如点击链接、填写表单等),直到用户关闭浏览器窗口或会话超时,整个过程就被视为一个会话。
区别
- 生命周期:
- sessionStorage:生命周期与当前会话一致,一旦会话结束关闭,不再存在。
- localStorage:其生命周期是永久的,除非用户手动删除数据或浏览器清理了存储。
- 存储大小:
- sessionStorage和localStorage的存储大小限制通常是相同的,大多数现代浏览器都提供了大约5MB的存储空间。
- 数据共享:
- sessionStorage的数据只能在当前会话的页面之间共享,且仅限于同源(相同的协议、域名和端口)的页面。
- localStorage的数据可以在所有同源页面之间共享,无论它们是否属于同一个会话。
- 数据格式:
- sessionStorage和localStorage都只能存储字符串类型的数据。如果需要存储复杂对象,可以使用JSON.stringify()方法将对象转换为json字符串,然后在需要时使用JSON.parse()方法将其还原为对象。
- 访问方式:
- 可以通过window.sessionStorage和window.localStorage来访问这两个存储对象。它们提供了setItem()、getItem()、removeItem()、clear()等方法来操作存储的数据。
- 使用场景:
- sessionStorage适用于存储只需要在当前会话期间保持有效的数据,例如用户的临时登录信息、表单的临时数据等。
- localStorage适用于存储需要长期保持的数据,例如用户的偏好设置、缓存的数据等。
注意事项
- 在使用sessionStorage和localStorage时,需要注意浏览器的兼容性问题。虽然现代浏览器大多支持这两个存储对象,但在一些旧版本的浏览器上可能存在兼容性问题。
- 在存储敏感数据时,需要注意安全性问题。虽然这两个存储对象都提供了在客户端存储数据的功能,但它们并不提供加密或身份验证等安全机制。因此,在存储敏感数据时,需要采取额外的安全措施来保护数据的安全性。
cookie session token
http 无状态
HTTP是一个无状态协议,每个HTTP请求都是独立的,服务器不会保存与先前请求相关的信息。
它指的是服务器在处理客户端的请求时,不会将请求和先前状态相关联。
但是在需要客户端与服务器进行动态交互的Web应用程序中,服务器需要记住上一次请求的信息。例如,在购物车功能中,服务器需要知道用户在商品浏览页面添加的商品信息,以便在购物车页面中显示。由于HTTP是无状态的,服务器无法直接获取这些信息。
1)Cookie:
Cookie 是存储在用户浏览器端的一个小型数据文件,用于跟踪和保存用户的状态信息。
主要用于保持用户登录状态、跟踪用户行为、存储用户偏好等。
存储在浏览器端。
2)Session:
Session 是服务器端保存用户状态的机制,每个用户会话都有一个唯一的 Session ID。
主要用于跟踪用户在服务器上的状态信息,例如登录状态和购物车内容。
存储在服务器端,然后对应的 Session ID 通过 Cookie 保存在客户端浏览器中。
3)Token:
Token 本质是一种加密的字符串,用于身份验证和授权,可以包含用户信息和权限,用于验证用户身份或授权访问资源。
认证后,后端服务会返回 Token,存储在客户端(浏览器或移动应用中),后续客户端访问服务端需要带上这个 Token。
它们之间使用场景区别:
- Cookie:主要用于客户端状态的简单存储和追踪。
- Session:用于服务器端的复杂状态管理,特别是在需要存储大量会话数据时。
- Token:用于无状态的认证和授权,特别是在分布式和跨域环境下。
简单来说,Cookie 和Session 更适合用于单次会话的认证和状态管理,而 Token 更适合用于跨会话的认证和状态管理。
什么是xss攻击,如何防范
XSS攻击,即跨站脚本攻击(Cross Site Scripting),是一种代码注入攻击。攻击者通过在网站注入恶意脚本,使之在用户的浏览器上运行,从而盗取用户的信息如cookie等。
XSS的本质是因为网站没有对恶意代码进行过滤,与正常的代码混合在一起了,浏览器没有办法分辨哪些脚本是可信的,从而导致了恶意代码的执行。
XSS 攻击,全称是跨站脚本攻击(Cross-Site Scripting),是一种代码注入攻击方式。攻击者通过在网页中注入恶意的脚本(通常是 JavaScript 代码),当用户浏览该网页时,恶意脚本就会在用户的浏览器中执行,从而达到劫持用户会话、伪造用户输入、窃取用户信息等目的。
防范 XSS 攻击的主要方法可以归纳为以下几点: 1)输入验证:对用户提交的信息进行严格的合法性检查,过滤或清理可能包含的恶意代码。 2)输出编码:对输出内容进行适当的编码,确保即便含有恶意代码也不会被执行。 3)使用安全库:使用诸如 Content Security Policy (CSP) 等浏览器提供的安全机制。 4)避免使用危险的 HTML 标签或属性,如 <script>
、<iframe>
和 onerror
事件处理程序等。
什么是csrf攻击,如何防范
CSRF(Cross-Site Request Forgery)攻击,即跨站请求伪造,这种攻击利用用户在已登录网站上的身份验证信息,在用户不知情的情况下,冒充用户向服务器发送恶意请求,从而执行未经用户授权的操作。
CSRF攻击的原理
CSRF攻击通常发生在用户已经登录了某个网站的情况下。攻击者会在自己的网站上构造一个恶意链接或表单,诱导用户点击该链接或提交表单。由于用户已经登录了目标网站,并且浏览器会自动携带用户的身份信息(如Cookie、Session等),因此恶意请求会携带用户的身份信息发送到目标网站。目标网站无法区分是用户自己发起的请求还是攻击者伪造的请求,因此容易受到攻击。
防范措施
为了防范CSRF攻击,可以采取以下措施:
- 使用CSRF令牌(Token):
- 在每个用户请求中生成唯一的CSRF令牌,并将其嵌入到表单或URL中。
- 服务器在接收到请求时验证令牌的合法性,只有包含正确令牌的请求才被认为是合法的。
- 检查Referer字段:
- 服务器可以通过检查HTTP请求头中的Referer字段来验证请求的来源是否合法。
- 但需要注意,Referer字段可能会被更改或伪造,因此这种方法并非完全可靠,通常作为辅助手段使用。
- 设置SameSite属性:
- 通过为Cookie设置SameSite属性为Strict或Lax,可以限制Cookie的发送,阻止跨站点请求。
- Strict模式下,Cookie仅在同源请求中发送;Lax模式下,Cookie在部分跨站请求(如GET请求)中不发送,但在表单提交等操作时仍会发送。
- 双重提交Cookie:
- 在每个请求中,同时通过Cookie和请求参数提交一个相同的token。
- 服务器端验证两者是否一致,以确保请求的有效性。
- 用户教育和安全意识:
- 用户应该时刻保持警惕,不点击不信任的链接,尤其是来自未知或可疑来源的链接。
- 定期更新操作系统和浏览器,并使用安全可靠的防病毒软件。
- 定期更新和维护网站:
- 开发人员和管理员应定期更新和维护网站,修补已知的漏洞,并及时应用安全补丁。
- 启用CSRF保护:
- 在使用Spring Security等安全框架时,可以启用CSRF保护功能,自动为请求添加和验证CSRF令牌。
什么是回流与重绘
回流(Reflow)
回流是指浏览器重新计算元素的布局,位置和大小的过程。
常发生在以下过程:
- 添加或删除可见的 DOM 元素。
- 元素尺寸发生变化,如宽度、高度、边距、填充等。
- 页面布局发生变化,如改变窗口大小。
- CSS 伪类激活,如:hover。
- 计算 offsetWidth、offsetHeight 等属性。
重绘(Repaint)
重绘是浏览器在元素的外观发生变化,但不影响布局时所发生的过程。
重绘通常发生在场景:
- 改变元素的颜色、背景、边框等样式,但不影响元素尺寸和位置。
回流与重绘的关系
- 触发条件:回流通常是在DOM结构或元素布局发生变化时触发,而重绘则是在元素样式属性发生变化时触发。
- 性能开销:由于回流需要重新计算元素的位置和大小,所以性能开销较大。而重绘只是重新绘制元素的外观,开销相对较小。
- 必然联系:回流必然伴随着重绘。当元素的位置和大小发生改变时,不仅需要进行回流计算,还需要进行重绘操作。但重绘不一定会引起回流。
减少回流和重绘的方法:
- 避免频繁操作样式:多次修改样式时,可以使用一个 class 来修改,或者通过修改 style 属性进行批量操作。
- 避免逐项改变样式:使用 CSS 的 transform、opacity 等属性进行动画,而不是改变宽度、高度、位置等会触发回流的属性。
- 使用文档片段(DocumentFragment)或者 offscreen 元素进行批量操作:在对 DOM 元素进行大量操作时,可以先将它们从文档流中移除,然后在内存中进行操作,最后再插入文档流中。
- 避免使用 table 布局:table 布局中的元素发生回流时,会影响到整个表格,从而导致更多的回流。
- 对具有复杂动画的元素使用绝对定位:将动画元素脱离文档流,减少回流对其他元素的影响。
- 避免频繁访问布局信息:如 offsetWidth、offsetHeight 等,可以在访问前将这些值缓存起来,避免多次触发回流。
什么是浏览器的同源策略
浏览器的同源策略(Same-Origin Policy)是一种安全策略,
它规定了浏览器只允许当前网页的脚本与来自同一站点(协议、主机、端口号相同)的窗口进行交互,而限制了与不同源(协议、主机、端口号任一不同)的窗口进行交互。这种限制能够有效保障用户的信息安全和隐私。
然而,有时需要在不同源之间进行数据交换,为此引入了一些跨域解决方案,如跨域资源共享(CORS)和跨文档消息传递(PostMessage)等。这些解决方案允许在特定条件下进行跨域交互,同时保持了一定的安全性。
如何解决跨域问题
跨域问题(Cross-Origin Resource Sharing,CORS)是由于浏览器的同源策略(Same-Origin Policy)导致的。同源策略指的是,如果两个 URL 的协议、主机名和端口号都相同,那么它们就是同源的,否则就是跨域的。当网页发起跨域请求时,浏览器会根据同源策略限制请求。解决跨域问题的方法有以下
1. CORS(跨域资源共享)
CORS 是一种通过添加一些 HTTP 头来允许浏览器跨域访问资源的机制,主要是服务端配置。服务端需要在响应头中添加 Access-Control-Allow-Origin 和其他一些参数,指示允许哪些域名进行跨域请求
- 优点:实现简单,只需要服务器端配置响应头。
- 缺点:需要服务器端的支持和配置。
在 Spring Boot 项目中,可以通过以下方式实现 CORS:
- 使用
@CrossOrigin
注解在方法或类上。 - 通过配置文件实现全局跨域。
- 通过
CorsFilter
对象实现全局跨域。
2. JSONP(JSON with Padding)
JSONP 是一种利用 <script>
标签的跨域请求方式。它通过动态创建一个 <script>
标签,并将跨域请求的 URL 作为其 src
属性。服务器端需要将响应的数据以函数调用的形式返回,客户端通过定义对应的回调函数来接收数据。
实现原理是在服务端生成一个 JavaScript 函数,客户端使用 < script > 标签请求该函数,服务端返回该函数的调用,并将需要传输的数据作为函数参数传入。
- 优点:兼容性好,可以解决主流浏览器的跨域问题。
- 缺点:仅支持 GET 请求,不安全,可能遭受 XSS 攻击。
3. 代理服务器
可以通过搭建一个代理服务器(如 Node.js、Nginx)来转发跨域请求。
客户端将跨域请求发送到代理服务器,代理服务器再将请求转发到目标服务器,目标服务器返回的数据经过代理服务器后再返回给客户端。
- 优点:可以解决跨域问题,同时可以对请求和响应进行更多的控制和定制。
- 缺点:需要额外的开发和维护工作。
4. WebSocket
WebSocket 是一种基于 TCP 的全双工通信协议,它允许客户端和服务器之间建立持久的连接,并进行实时的双向数据传输。通过 WebSocket,跨域通信可以更加高效和实时。
- 优点:适用于需要实时通信的场景,如实时聊天、实时数据推送等。
- 缺点:需要客户端和服务器都支持 WebSocket 协议。
浏览器渲染过程
- DNS查询,解析域名:
- 当用户在浏览器中输入一个网址时,浏览器首先会进行DNS查询,将域名解析为对应的IP地址。
- 建立TCP连接:
- 浏览器与服务器之间需要建立TCP连接,以便进行数据传输。
- 发出HTTP请求:
- 浏览器通过HTTP协议向服务器发送请求,请求获取网页资源。
- 等待服务器响应:
- 服务器接收到请求后,会处理请求并返回相应的资源,如HTML、CSS、JavaScript、图片等。
- 浏览器接收并解析资源:
- 浏览器接收到服务器返回的资源后,会开始解析这些资源。
- 解析HTML:浏览器会解析HTML文档,构建DOM树(文档对象模型)。DOM树是HTML文档在内存中的表示形式,它包含了文档中的所有元素和它们的层次关系。
- 解析CSS:同时,浏览器会解析CSS样式表,构建CSSOM树(CSS对象模型)。CSSOM树表示了文档中所有元素的样式信息。
- 解析JavaScript:如果HTML文档中包含了JavaScript代码,浏览器会解析并执行这些代码。JavaScript代码可能会修改DOM树或CSSOM树。
- 浏览器接收到服务器返回的资源后,会开始解析这些资源。
- 构建渲染树:
- 在构建完DOM树和CSSOM树之后,浏览器会结合这两个树来构建渲染树。渲染树只包含可见元素和它们的样式信息。
- 布局(Layout):
- 浏览器会根据渲染树计算每个元素的几何信息(如位置、大小等),这个过程称为布局或回流。
- 绘制(Painting):
- 最后,浏览器会将渲染树的每个节点绘制到屏幕上。这个过程称为绘制或重绘。
script中的defer 和 async的区别
控制脚本异步加载的属性,执行时机不同,defer会在html文件加载完成之后执行,async则会在加载完成之后立即执行不管html是否还在加载中
defer属性
- 加载方式:使用
defer
属性的脚本会在HTML解析的同时异步加载。 - 执行顺序:所有带有
defer
属性的脚本会按照它们在页面中的出现顺序依次执行。 - 执行时机:脚本会在HTML文档解析完毕后执行,也就是在
DOMContentLoaded
事件触发之前执行,但不会阻塞页面的解析。 - 适用场景:当脚本依赖于DOM结构时,使用
defer
是理想的,因为它保证了脚本执行时DOM已经完全加载完成。
async属性
- 加载方式:使用
async
属性的脚本也会异步加载,与HTML解析同时进行。 - 执行顺序:脚本会在加载完成后立即执行,不保证按照它们在页面中的出现顺序执行。
- 执行时机:一旦脚本加载完成,就会立即执行,可能会在HTML解析完成之前执行,也可能在解析过程中执行。
- 适用场景:用于独立、不依赖于其他脚本或DOM内容的脚本,例如分析工具或广告脚本,因为它们可以尽快执行而不影响页面的解析。
总结
- 加载顺序:
async
无序(哪个脚本先加载完哪个先执行),defer
有序(按照HTML中的顺序执行)。 - 执行时机:
async
脚本一旦加载完成立刻执行,defer
脚本会在HTML解析完成之后执行。 - 使用建议:
- 当脚本依赖于页面的DOM结构时,使用
defer
更安全。 - 当脚本与其他脚本和页面结构无关时,可以使用
async
以加快加载和执行速度。
- 当脚本依赖于页面的DOM结构时,使用
v8引擎的垃圾回收机制如何工作
V8引擎简介
V8是一种开源的JavaScript引擎,它主要用于Chrome浏览器和Node.js环境。V8引擎中的垃圾回收机制负责自动管理内存的分配和释放,以确保程序运行期间不会出现内存泄漏或垃圾堆积的问题。
垃圾回收机制原理
V8引擎的垃圾回收机制基于代际假说和分代回收的原理。代际假说认为,大部分对象在内存中存在的时间很短,而少数对象会存活较长时间。因此,V8将内存分为新生代(young generation)和老生代(old generation)两个区域。
- 新生代(Young Generation):
- 用于存放新创建的对象。
- 空间相对较小,因为大部分对象很快就会被回收。
- 使用Scavenge算法进行垃圾回收。该算法将新生代内存空间分为From空间和To空间。新创建的对象首先被分配到From空间,当From空间满时,会触发垃圾回收过程。回收过程中,V8首先进行标记操作,标记活跃的对象,然后将这些对象复制到To空间,同时进行压缩等操作。最后,From空间和To空间的角色互换,完成垃圾回收。
- 老生代(Old Generation):
- 用于存放经过一定时间仍然存活的对象。
- 空间相对较大,因为老生代中的对象存活时间较长。
- 使用标记-清除(Mark-Sweep)和标记-压缩(Mark-Compact)两种算法进行垃圾回收。标记-清除算法首先进行标记操作,标记出活跃的对象,然后清除未标记的对象。标记-压缩算法在清除未标记的对象后,将存活的对象压缩到内存的一端,从而减少内存碎片化。
增量标记与并行回收
- 增量标记:为了避免长期停顿,V8 会在标记阶段使用增量标记来将工作切成更小的块。
- 并发回收:在清除阶段,V8 支持并发回收,使得垃圾回收工作可以在多个线程上并行进行,从而减少主线程停顿时间。
垃圾回收过程
- 标记阶段:遍历所有对象,将可达的活动对象进行标记。
- 清理阶段:统一清理内存中被标记为可回收的对象。
- 内存整理阶段:当清理完内容后,会存在大量不连续的空间,因此需要重新整理内存,使存活的对象在内存地址上变得连续。
对象晋升
在新生代中,当一个对象经过多次复制仍然存活时,或者当To空间的内存占用比超过限制时(如25%),该对象会被晋升到老生代。老生代中的对象由于存活时间较长,垃圾回收的成本较高,因此使用更高效的算法进行处理。
进程与线程的区别
- 资源分配:进程是资源分配的基本单位,每个进程都有独立的地址空间和资源;而线程是CPU调度的基本单位,线程共享进程的地址空间和资源。
- 独立性:进程之间是相互独立的,一个进程的崩溃不会影响其他进程;而线程是进程的一部分,一个线程的崩溃会导致整个进程的崩溃(在保护模式下,其他线程可能会受到影响,但整个进程通常会被终止)。
- 开销:进程切换需要较大的开销,因为需要保存和恢复上下文信息等;而线程切换开销相对较小,因为线程共享进程的地址空间和资源。
- 通信:进程间通信需要通过特定的机制,如管道、消息队列等;而线程之间可以直接通过共享内存进行通信和数据共享。
- 并发性:线程可以实现更加高效的并发编程,因为线程之间的切换开销小且可以共享进程的资源;而进程在并发编程中相对较重,因为需要处理进程间通信和资源分配等问题。
js是单线程还是多线程的
javaScript的单线程特性
JavaScript在浏览器和Node.js环境中是单线程的,这意味着它在同一时间只执行一个任务。
这种设计主要是为了简化代码逻辑,避免并发导致的复杂性,并减少潜在的错误。
由于JavaScript可以操作DOM,如果多个线程同时操作DOM,可能会导致浏览器混乱。因此,单线程模型可以确保DOM操作的一致性和安全性。
事件循环和异步操作
虽然JavaScript是单线程的,但它通过事件循环机制来处理异步操作。当执行一个函数时,它会被推入调用栈=,执行完后出栈。如果遇到异步操作(如网络请求、定时器等),JavaScript会将这些操作放入任务队列。事件循环不断检查调用栈是否为空,如果栈为空,它会从任务队列中取出下一个任务并将其推入栈中执行。这种方式使得JavaScript能够处理异步事件,而不会阻塞主线程。
Web Workers支持多线程
虽然JavaScript在主线程上是单线程的,但它通过Web Workers API支持多线程。Web Workers允许在后台线程中运行JavaScript代码,进行并行处理。这些后台线程与主线程(UI线程)相互独立,彼此之间通过消息传递(postMessage
)进行通信。这种方式可以提高应用程序的性能,特别是在处理计算密集型任务时,而不会阻塞UI线程。
总结
因此,可以说JavaScript在单线程的基础上,通过事件循环机制实现了异步操作,并通过Web Workers支持了多线程的并行处理。
浏览器渲染进程的线程有哪些
浏览器渲染进程主要负责将HTML、CSS和JavaScript等文件解析为用户可以交互的网页。这个进程是多线程的,主要包括以下几个关键线程:
- GUI渲染线程(Rendering Thread):
- 负责渲染页面,包括解析HTML、CSS,构建DOM树、CSSOM树、渲染树,以及绘制页面。
- 当界面需要重绘或由于某种操作引发回流时,该线程就会执行。
- GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时,GUI线程会被挂起,GUI更新会被保存在一个队列中,等到JS引擎空闲时立即被执行。
- JS引擎线程(JavaScript Engine Thread):
- 也称为JS内核,负责处理JavaScript脚本程序,解析JavaScript脚本并运行代码。
- 一个Tab页中无论什么时候都只有一个JS引擎线程在运行JavaScript程序。
- 由于GUI渲染线程与JS引擎线程的互斥关系,如果JS执行时间过长,会造成页面的渲染不连贯,导致页面渲染加载阻塞。
- 事件触发线程(Event Dispatch Thread):
- 属于浏览器而不是JS引擎,负责处理JavaScript代码中的事件,控制事件循环。
- 当JS引擎执行代码块(如
setTimeout
)或来自浏览器内核的其他线程(如鼠标点击、AJAX异步请求等)触发事件时,会将对应任务添加到事件触发线程中。 - 当对应的事件符合触发条件时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。
- 定时器线程(Timer Thread):
- 负责定时器功能,如
setInterval
和setTimeout
。 - 浏览器定时计数器并不是由JS引擎计数的,因为JS引擎是单线程的。如果处于阻塞状态,就会影响计时的准确性。因此,使用单独线程来计时并触发定时器。
- 计时完毕后,定时器线程会将任务添加到事件队列中,等待JS引擎空闲后执行。所以,定时器中的任务在设定的时间点不一定能够准时执行,定时器只是在指定时间点将任务添加到事件队列中。
- 负责定时器功能,如
- 异步HTTP请求线程:
- 负责处理网络请求,如通过
XMLHttpRequest
发起的异步请求。 - 检测到状态变更时,如果设置有回调函数,异步线程会产生状态变更事件,并将回调函数放入事件队列中,等待JS引擎空闲后执行。
- 负责处理网络请求,如通过