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

百度网盘golang实习面经

在这里插入图片描述

goroutine内存泄漏的情况?如何避免?

goroutine内存泄漏基本上是因为异常导致阻塞, 可以导致阻塞的情况
1 死锁, goroutine 等待的锁发生了死锁情况
2 chan没有正常被关闭,导致读取读chan的goroutine阻塞
如何避免
1 避免死锁
2 正常关闭
3 使用context管理goroutine, 超时结束goroutine

在Go语言中,Goroutine内存泄漏通常是由于Goroutine未能正确退出,导致其引用的对象无法被垃圾回收(GC)。以下是常见的内存泄漏场景及避免方法:


常见Goroutine内存泄漏场景

  1. 无限循环未设退出条件

    go func() {for { // 无退出条件// 持续执行任务...}
    }()
    
  2. 阻塞于未处理的Channel操作

    ch := make(chan int)
    go func() {<-ch // 永久阻塞,无数据发送
    }()
    
  3. 生产者提前退出,消费者未关闭

    func consumer(ch <-chan int) {for v := range ch { // 若生产者未关闭ch,消费者永久阻塞// 处理v}
    }
    
  4. 未释放资源(如time.Ticker)

    go func() {ticker := time.NewTicker(time.Second)for {<-ticker.C // 未调用ticker.Stop()}
    }()
    
  5. WaitGroup使用不当

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {// 忘记调用wg.Done()
    }()
    wg.Wait() // 永久阻塞
    

避免内存泄漏的方法

1. 使用context.Contextdone通道通知退出
  • 通过context的取消机制或自定义done通道,明确控制Goroutine生命周期。
ctx, cancel := context.WithCancel(context.Background())
defer cancel()go func(ctx context.Context) {for {select {case <-ctx.Done(): // 收到退出信号returndefault:// 执行任务}}
}(ctx)
2. 避免永久阻塞:超时与select结合
  • 为Channel操作添加超时,防止永久阻塞。
select {
case <-ch:// 正常处理
case <-time.After(1 * time.Second):// 超时处理
}
3. 正确关闭Channel
  • 确保生产者完成后关闭Channel,或在退出时通过done通道通知消费者。
done := make(chan struct{})
ch := make(chan int)go func() {defer close(ch) // 确保关闭Channel// 生产数据
}()go func() {for {select {case v, ok := <-ch:if !ok {return}// 处理vcase <-done: // 外部终止信号return}}
}()
4. 释放资源(如Ticker、锁、文件句柄)
  • 使用defer确保资源释放。
go func() {ticker := time.NewTicker(time.Second)defer ticker.Stop() // 确保停止Tickerfor {select {case <-ticker.C:// 执行任务case <-done:return}}
}()
5. 正确使用sync.WaitGroup
  • 使用defer wg.Done()避免遗漏。
var wg sync.WaitGroup
wg.Add(1)
go func() {defer wg.Done() // 确保调用Done()// 执行任务
}()
wg.Wait()
6. 监控Goroutine数量
  • 使用pprofruntime.NumGoroutine()诊断泄漏。
import (_ "net/http/pprof""net/http"
)func main() {go http.ListenAndServe(":6060", nil) // 暴露pprof接口// ...
}

访问http://localhost:6060/debug/pprof/goroutine?debug=2查看Goroutine堆栈。


总结

  • 设计原则:确保每个Goroutine都有明确的退出路径。
  • 资源管理:通过defercontextdone通道管理生命周期。
  • 工具辅助:利用pprof等工具监控和诊断泄漏。

遵循以上实践,可有效避免Goroutine内存泄漏问题。

讲一下协程和线程的区别?从多个角度说明,讲一下golang协程是如何调度的,和java线程的区别

主要的区别在于协程是用户级, 不需要进入到内核态处理. 所以协程更加轻量级, 不占用内核资源。2k
协程(Goroutine)和线程(Thread)是并发编程中的核心概念,它们在设计目标、资源管理、调度方式等方面有显著差异。以下是两者的详细对比,并重点分析 Go 协程的调度机制及其与 Java 线程的区别。


一、协程与线程的核心区别

角度协程(Goroutine)线程(Thread)
调度主体由用户态调度(Go 运行时调度器)由操作系统内核调度
内存占用初始栈约 2KB,可动态扩展(最大默认 1GB)固定栈(如 Linux 默认 8MB,Java 线程约 1MB)
切换成本极低(无需内核切换,仅用户态操作)高(需陷入内核态,上下文切换开销大)
并发数量轻松支持百万级并发(资源占用小)通常最多数千(受内核资源限制)
同步机制基于 Channel 通信(CSP 模型),避免共享内存依赖锁、信号量等(共享内存,需显式同步)
错误处理通过 panic/recover 或返回值传递错误通过异常捕获(如 try-catch
创建与销毁极快(由 Go 运行时管理,无系统调用)较慢(需系统调用,内核分配资源)

二、Go 协程的调度机制(GMP 模型)

Go 的协程调度器采用 GMP 模型,由以下三部分组成:

  1. G(Goroutine):协程对象,存储执行栈和状态。
  2. M(Machine):操作系统线程(实际执行单元),由内核调度。
  3. P(Processor):逻辑处理器,管理本地协程队列(每个 P 绑定一个 M)。
调度流程
  1. 协程创建
    当启动一个 Goroutine 时,它会被放入当前 P 的本地队列(或全局队列,若本地队列满)。

  2. 线程绑定(M 与 P 绑定)
    每个 P 会绑定一个 M(操作系统线程),M 从 P 的本地队列中获取 G 并执行。

  3. 协作式与抢占式调度

    • 协作式:协程主动让出 CPU(如 runtime.Gosched() 或系统调用)。
    • 抢占式:Go 1.14+ 引入基于信号的抢占,防止协程长时间占用 CPU。
  4. Work Stealing
    若某个 P 的本地队列为空,会尝试从其他 P 的队列或全局队列“窃取” G,提高 CPU 利用率。

  5. 系统调用优化

    • 当 G 执行系统调用时,M 会解绑 P,P 转而绑定其他空闲 M,避免阻塞其他 G。
    • 系统调用完成后,M 尝试获取 P 继续执行,若无可用 P,则 G 进入全局队列。

三、Go 协程与 Java 线程的对比

1. 调度方式
  • Go 协程
    • 由 Go 运行时调度,用户态协作式+抢占式混合调度。
    • 无需内核介入,切换成本极低(如保存/恢复少量寄存器)。
  • Java 线程
    • 依赖操作系统内核调度(完全抢占式)。
    • 线程切换需陷入内核态,上下文切换开销大(如保存线程状态、切换页表等)。
2. 资源占用
  • Go 协程
    • 初始栈 2KB,按需动态扩展(避免内存浪费)。
    • 协程复用线程(M),1 个线程可运行数千个协程。
  • Java 线程
    • 固定栈大小(默认约 1MB),大量线程易导致内存耗尽。
    • 线程与内核线程 1:1 绑定,创建过多会触发 OOM。
3. 并发能力
  • Go 协程
    • 轻松支持百万级并发(如 Web 服务器处理海量连接)。
    • 典型场景:IO 密集型任务(网络、磁盘操作)。
  • Java 线程
    • 线程数量受限于内核(通常数千级别)。
    • 需结合线程池避免资源耗尽,但高并发时仍有瓶颈。
4. 同步与通信
  • Go 协程
    • 通过 Channel 通信,遵循 CSP 模型(“不要通过共享内存通信,而通过通信共享内存”)。
    • 天然避免竞态条件,减少锁的使用。
  • Java 线程
    • 依赖 synchronizedLockvolatile 等同步机制。
    • 共享内存模型易引发死锁、数据竞争等问题。
5. 错误处理
  • Go 协程
    • 错误通过返回值或 panic/recover 传递。
    • 若协程发生未捕获的 panic,整个程序会终止。
  • Java 线程
    • 异常需在线程内捕获,否则导致线程终止但进程不退出。
    • 可通过 Future 或全局异常处理器(UncaughtExceptionHandler)处理。

四、总结

特性Go 协程Java 线程
调度开销极低(用户态调度)高(内核态调度)
适用场景高并发、IO 密集型任务CPU 密集型任务、少量并发
资源占用极小(动态栈,复用线程)大(固定栈,线程与内核线程 1:1 绑定)
并发模型CSP 模型(Channel 通信)共享内存模型(锁同步)
调试复杂度较低(天然避免部分竞态条件)较高(需处理死锁、数据竞争)

五、为什么 Go 协程更适合高并发?

  1. 轻量级:协程创建和切换成本极低,允许海量并发。
  2. 高效调度:GMP 模型减少线程阻塞,最大化 CPU 利用率。
  3. 简化同步:Channel 取代锁,降低并发编程复杂度。
  4. 资源友好:动态栈和用户态调度避免内存和内核资源浪费。

七、结论

  • 协程是用户态的轻量级抽象,适合高并发、IO 密集型场景。
  • 线程是操作系统资源,适合 CPU 密集型任务,但需谨慎管理。
  • Go 的 GMP 调度器通过解耦协程与线程,结合协作式与抢占式调度,实现高效并发。
  • Java 线程受限于内核调度和资源开销,需依赖线程池等技术优化,但并发能力仍弱于协程。

slice和array的区别,讲一下底层的结构

array本质是一个固定数组, 内存层面就是一块固定的内存区域,不会改变, 传递的时候是拷贝一份完整数据.
slice本质上是一个动态数组的封装,底层指向不是一个固定内存,可以重新指向新的内存,包含一个指向 Array 的指针、长度和容量。

channel的用途和使用上要注意的点,底层的结构是怎样的

channel是golang中协程之间的数据交互的重要工具,相当于与进程内的一个消息队列.
注意点: 最重要的是chan的close处理, 不然很容易出现异常, 1写数据goroutine中调用close, 2不要多次调用close, 3使用信号通知chan close了
底层结构: 环形队列(缓存数据, 无缓存的时候用不上), 读goroutine 队列(链表), 写goroutine 队列(链表), 锁
在 Go 语言中,Channel(通道) 是 Goroutine 之间通信和同步的核心机制,基于 CSP 模型(Communicating Sequential Processes)。以下是 Channel 的用途、使用注意事项及其底层结构的详细分析。


一、Channel 的用途

  1. Goroutine 间通信

    • 传递数据:通过 ch <- data(发送)和 data := <-ch(接收)实现数据交换。
    • 替代共享内存:遵循 Go 的哲学——“不要通过共享内存通信,而要通过通信共享内存”。
  2. 同步控制

    • 阻塞等待:无缓冲 Channel 的发送和接收会阻塞,直到对方准备好(天然的同步机制)。
    • 协调多个 Goroutine:例如通过 close(ch) 通知接收方数据结束。
  3. 工作池和任务分发

    • 结合缓冲 Channel,可构建生产者-消费者模型,控制并发数量。
  4. 超时控制

    • 通过 select 结合 time.After 实现超时机制:
      select {
      case <-ch:// 正常处理
      case <-time.After(1 * time.Second):// 超时处理
      }
      

二、使用 Channel 的注意事项

1. 初始化与零值
  • Channel 的零值为 nil,向 nil Channel 发送或接收会永久阻塞:
    var ch chan int // ch 是 nil
    ch <- 1         // 永久阻塞(无 panic)
    <-ch            // 永久阻塞(无 panic)
    
  • 正确做法:使用 make 初始化 Channel:
    ch := make(chan int)     // 无缓冲 Channel
    bufferedCh := make(chan int, 10) // 缓冲容量为 10
    
2. 避免死锁
  • 无缓冲 Channel 的同步性:发送和接收必须成对出现,否则死锁。
    func main() {ch := make(chan int)ch <- 1          // 发送后阻塞,无接收者导致死锁fmt.Println(<-ch) // 永远不会执行
    }
    
  • 解决方式:确保发送和接收在不同的 Goroutine 中:
    go func() { ch <- 1 }()
    fmt.Println(<-ch)
    
3. 关闭 Channel 的规则
  • 关闭后不可发送:向已关闭的 Channel 发送数据会引发 panic
  • 接收已关闭的 Channel:可继续接收剩余数据,返回零值时需通过 ok 判断是否关闭:
    v, ok := <-ch
    if !ok {// Channel 已关闭
    }
    
  • 关闭 Channel 的原则
    • 只由发送方关闭,避免多个 Goroutine 同时关闭。
    • 无需关闭 Channel(除非必须通知接收方“数据结束”)。
4. 避免泄漏
  • 未关闭的 Channel:若接收方持续等待已不再发送数据的 Channel,会导致 Goroutine 泄漏。
  • 解决方式:使用 contextdone 通道通知退出:
    done := make(chan struct{})
    go func() {select {case <-done:returncase v := <-ch:// 处理数据}
    }()
    // 退出时关闭 done
    close(done)
    
5. 性能优化
  • 缓冲 Channel:减少阻塞频率,但需权衡内存占用。
  • 避免过度缓冲:缓冲大小应根据实际场景调整,避免资源浪费。

三、Channel 的底层结构

Go 的 Channel 实现基于 runtime.hchan 结构体(源码见 runtime/chan.go),核心字段如下:

1. hchan 结构体
type hchan struct {qcount   uint          // 当前队列中元素数量dataqsiz uint          // 缓冲区的固定大小(容量)buf      unsafe.Pointer // 指向环形缓冲区的指针elemsize uint16        // 元素大小closed   uint32        // 是否已关闭(0-未关闭,1-已关闭)sendx    uint          // 发送索引(指向缓冲区下一个写入位置)recvx    uint          // 接收索引(指向缓冲区下一个读取位置)recvq    waitq         // 等待接收的 Goroutine 队列(sudog 链表)sendq    waitq         // 等待发送的 Goroutine 队列(sudog 链表)lock     mutex         // 互斥锁(保护 Channel 的并发操作)
}
2. 环形缓冲区(Buffered Channel)
  • 缓冲机制:当 dataqsiz > 0 时,Channel 使用环形队列存储数据。
  • 写入流程
    • 若缓冲区未满,数据写入 buf[sendx]sendx = (sendx + 1) % dataqsiz
    • 若缓冲区已满,发送方 Goroutine 加入 sendq 队列并阻塞。
  • 读取流程
    • 若缓冲区非空,读取 buf[recvx]recvx = (recvx + 1) % dataqsiz
    • 若缓冲区为空,接收方 Goroutine 加入 recvq 队列并阻塞。
3. 直接发送与接收(Unbuffered Channel)
  • 无缓冲 Channeldataqsiz = 0,发送和接收必须同时就绪。
  • 同步过程
    • 若接收方已阻塞(在 recvq 中),发送方直接将数据拷贝到接收方的栈。
    • 若发送方已阻塞(在 sendq 中),接收方直接从发送方拷贝数据。
4. 等待队列(waitq
  • 阻塞的 Goroutine:当发送或接收无法立即完成时,Goroutine 被封装为 sudog 结构体,加入 sendqrecvq 队列。
  • 唤醒机制:当条件满足时(如缓冲区有空间或数据),调度器唤醒队列中的 Goroutine。

四、总结

特性说明
核心用途Goroutine 间通信与同步,替代共享内存
底层结构基于环形缓冲区和等待队列(hchan),通过锁保证并发安全
注意事项避免死锁、正确关闭、处理零值、防止泄漏
性能优化合理使用缓冲、减少锁竞争、避免过度阻塞

Channel 是 Go 并发编程的核心工具,深入理解其机制和陷阱,能够编写出高效且健壮的并发代码。

orm框架的优缺点

orm封装了对数据库的操作,并且自动转换内存数据结构和数据库字段, 优点是方便,开发效率高, 缺点是有些场景性能低, 复杂对像转换处理起来不方便.

操作系统内核态和用户态的区别,何时进入内核态or用户态

在这里插入图片描述
进入内核态: 中断(系统调用, 时间片到期等)
进入用户态: 内核态处理完成,调度用户线程处理程序

tcp和udp的区别,他们的报头结构,tcp的三次握手和四次握手的中间状态有哪些

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

https中的TLS/SSL层是用来干什么的,讲一下根证书和证书链和https握手的流程


TLS/SSL 层的作用

TLS(Transport Layer Security) 及其前身 SSL(Secure Sockets Layer) 是位于传输层(如 TCP)和应用层(如 HTTP)之间的安全协议,主要用于:

  1. 加密通信:防止数据在传输过程中被窃听。
  2. 身份认证:验证服务器(或客户端)的身份,防止中间人攻击。
  3. 数据完整性:确保数据未被篡改(通过哈希算法和消息认证码)。

HTTPS = HTTP + TLS/SSL,所有数据在传输前会被 TLS 层加密。


根证书与证书链

1. 根证书(Root Certificate)
  • 颁发者:由受信任的根证书颁发机构(Root CA,如 DigiCert、Let’s Encrypt)签发。
  • 存储位置:预装在操作系统或浏览器中(如 Windows 的受信任根证书存储)。
  • 作用:作为信任链的起点,用于验证其他证书的合法性。
2. 证书链(Certificate Chain)
  • 结构根证书 → 中间证书(Intermediate CA) → 服务器证书
  • 示例
    • 根证书:DigiCert Global Root CA
    • 中间证书:DigiCert TLS RSA SHA256 2020 CA1
    • 服务器证书:www.example.com
  • 作用
    • 分层信任:根证书不直接签发服务器证书,通过中间证书隔离风险(即使中间证书私钥泄露,只需吊销中间证书,无需替换根证书)。
    • 链式验证:客户端从服务器证书逐级向上验证,直到找到信任的根证书。
3. 证书验证过程
  1. 客户端收到服务器的证书(如 www.example.com)。
  2. 检查证书是否过期、域名是否匹配。
  3. 通过证书链向上追溯,验证每一级证书的签名是否合法,直到找到受信任的根证书。
  4. 若验证失败(如根证书不在信任库中),浏览器会提示“证书不受信任”。

HTTPS 握手流程(以 TLS 1.2 为例)

以下是客户端(如浏览器)与服务器建立 HTTPS 连接的详细步骤:

1. Client Hello
  • 客户端发送:
    • 支持的 TLS 版本(如 TLS 1.2)。
    • 客户端随机数(Client Random,用于生成会话密钥)。
    • 支持的密码套件(如 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)。
    • SNI(Server Name Indication):指定访问的域名(用于多域名服务器)。
2. Server Hello
  • 服务器回应:
    • 选择的 TLS 版本密码套件
    • 服务器随机数(Server Random,用于生成会话密钥)。
    • 服务器证书链(包含服务器证书和中间证书)。
3. 证书验证
  • 客户端验证服务器证书链的合法性(如前文所述)。
4. 密钥交换(Key Exchange)
  • RSA 密钥交换(传统方式):
    • 客户端生成预主密钥(Pre-Master Secret),用服务器证书的公钥加密后发送。
    • 服务器用私钥解密,得到预主密钥。
  • ECDHE 密钥交换(现代方式,支持前向保密):
    • 服务器生成临时椭圆曲线参数和公钥(Server Params),签名后发送。
    • 客户端生成临时公钥(Client Params),发送给服务器。
    • 双方通过椭圆曲线算法生成预主密钥。
5. 生成会话密钥
  • 客户端和服务器使用以下三个随机数生成主密钥(Master Secret)
    • Client Random
    • Server Random
    • Pre-Master Secret
  • 主密钥进一步派生出会话密钥(对称加密密钥,如 AES 密钥),用于后续通信加密。
6. Finished
  • 双方发送加密的 Finished 消息,验证握手过程未被篡改。
  • 握手完成,后续应用数据通过对称加密传输。

TLS 1.3 的优化

TLS 1.3 简化握手流程,提升安全性和速度:

  1. 合并步骤:将密钥交换与证书验证合并为单次往返(1-RTT)。
  2. 移除不安全算法:禁用 RSA 密钥交换(仅支持前向保密的 ECDHE)。
  3. 0-RTT 模式:对重复连接可跳过握手(需谨慎使用,存在重放攻击风险)。

总结

关键点说明
TLS/SSL 作用加密数据、验证身份、保障完整性
根证书信任链的起点,预装在系统中
证书链分层签发,隔离风险,支持灵活吊销
握手流程协商参数 → 交换密钥 → 生成会话密钥 → 加密通信
前向保密ECDHE 确保即使服务器私钥泄露,历史会话仍安全(TLS 1.3 强制要求)

示例场景
当访问 https://www.example.com 时:

  1. 浏览器通过 TLS 握手验证服务器的证书链,确认其属于 example.com
  2. 双方协商出会话密钥,后续所有 HTTP 数据(如登录密码、支付信息)均通过 AES 加密传输,确保安全。

常见的攻击手法有哪些,讲一下中间人攻击和跨域攻击的原理,跨域攻击主要是利用了浏览器的什么机制


一、常见攻击手法分类

以下是网络安全中常见的攻击类型:

攻击类型描述
中间人攻击(MITM)攻击者拦截并篡改通信双方的数据流。
跨站脚本(XSS)向网页注入恶意脚本,窃取用户数据或会话 Cookie。
SQL 注入通过输入恶意 SQL 语句,操纵数据库查询。
跨站请求伪造(CSRF)诱使用户在已认证的站点上执行非预期的操作(如转账)。
拒绝服务(DoS/DDoS)通过大量请求耗尽目标资源,使其无法正常服务。
钓鱼攻击伪造可信页面(如银行网站),诱导用户提交敏感信息。
目录遍历/文件包含利用路径漏洞访问或执行服务器上的敏感文件。
社会工程学通过心理欺骗获取敏感信息(如假冒客服骗取密码)。

二、中间人攻击(MITM)原理

1. 攻击场景
  • 未加密的通信:如 HTTP 明文传输、公共 Wi-Fi 环境。
  • 证书欺骗:伪造 SSL/TLS 证书(如自签名证书),诱导用户信任。
2. 攻击步骤
  1. 窃听(Eavesdrop)
    攻击者通过 ARP 欺骗、DNS 劫持或 Wi-Fi 嗅探,成为通信链路的中间节点。

    • ARP 欺骗:伪造 IP 和 MAC 地址映射,劫持局域网流量。
    • DNS 劫持:篡改 DNS 响应,将域名解析到攻击者控制的 IP。
  2. 篡改或伪造数据

    • 修改传输内容(如插入广告、重定向到钓鱼网站)。
    • 窃取敏感信息(如登录凭证、Cookie)。
  3. 伪装身份

    • 在 HTTPS 场景下,攻击者可能伪造证书(需用户手动信任),解密 HTTPS 流量。
3. 防御措施
  • 使用 HTTPS:加密通信内容,防止明文数据泄露。
  • HSTS(HTTP Strict Transport Security):强制浏览器使用 HTTPS,防止降级攻击。
  • 证书固定(Certificate Pinning):客户端固定合法证书,拒绝非预期证书。
  • 网络层防护:使用 VPN、避免使用公共 Wi-Fi 进行敏感操作。

三、跨域攻击(Cross-Origin Attacks)原理

跨域攻击主要利用浏览器**同源策略(Same-Origin Policy)**的漏洞,绕过安全限制,窃取数据或执行恶意操作。

1. 同源策略(SOP)
  • 定义:浏览器限制脚本只能访问与当前页面同源(协议、域名、端口相同)的资源。
  • 目的:防止恶意网站读取其他站点的敏感数据(如 Cookie、DOM 内容)。
2. 跨域攻击类型
(1) 跨站脚本(XSS)
  • 原理:攻击者注入恶意脚本到合法页面,脚本在用户浏览器执行。
    <!-- 示例:通过未过滤的用户输入注入脚本 -->
    <input value="<script>stealCookie()</script>">
    
  • 利用点
    • 窃取用户的 Cookie 或 Session ID。
    • 伪造用户操作(如自动转账)。
(2) 跨站请求伪造(CSRF)
  • 原理:诱导用户访问恶意页面,该页面自动向目标站点发送已认证的请求。
    <!-- 恶意页面中隐藏的转账请求 -->
    <img src="https://bank.com/transfer?to=attacker&amount=1000000">
    
  • 利用点
    • 用户已登录目标站点(如银行),浏览器自动携带 Cookie。
    • 请求被执行(如转账、修改密码)。
(3) CORS 配置不当
  • 原理:服务器错误设置 Access-Control-Allow-Origin: *,允许任意域访问资源。
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    
  • 利用点
    • 攻击者通过恶意网站发起跨域 AJAX 请求,窃取数据。
(4) JSONP 劫持
  • 原理:利用 <script> 标签跨域加载 JSONP 接口,通过回调函数窃取数据。
    <script src="https://api.com/user?callback=stealData"></script>
    <script>
    function stealData(data) {// 发送数据到攻击者服务器
    }
    </script>
    
3. 防御措施
攻击类型防御方法
XSS输入输出过滤(如转义 <, >)、启用 CSP(Content Security Policy)。
CSRF使用 CSRF Token、检查 Referer 头、设置 SameSite Cookie 属性。
CORS严格限制 Access-Control-Allow-Origin(如白名单)、避免使用通配符 *
JSONP弃用 JSONP,改用 CORS;或校验回调函数名、添加随机 Token。

四、总结

攻击类型核心原理浏览器机制利用
中间人攻击拦截并篡改通信链路无加密通信或证书信任漏洞
跨域攻击绕过同源策略获取跨域数据或权限SOP 限制不严、CORS/JSONP 配置错误

关键点

  • 中间人攻击依赖网络层的漏洞,防御需加密通信(HTTPS)和身份验证。
  • 跨域攻击利用浏览器同源策略的宽松配置,防御需严格限制跨域资源访问。

示例场景

  • MITM:公共 Wi-Fi 中,攻击者截获用户登录 HTTP 站点的密码。
  • 跨域攻击:恶意网站利用银行站点的 CORS 配置错误,窃取用户账户数据。

通过理解攻击原理和浏览器机制,开发者可更有效地设计安全防护策略。

相关文章:

  • Linux架构篇、第1章_01架构的介绍HTTP HTTPS 协议全面解析
  • 2025华东杯ABC题赛题已出速拿
  • LabelVision - yolo可视化标注工具
  • 【mysql】执行过程,背诵版
  • Linux-04-用户管理命令
  • JAVA:使用 iTextPDF 处理 PDF 的技术详解
  • 树的序列化 - 学习笔记
  • 【自然语言处理与大模型】如何获取特定领域的微调数据集?
  • iview 如何设置sider宽度
  • 论文阅读:2024 ACM SIGSAC Membership inference attacks against in-context learning
  • 多模态大语言模型arxiv论文略读(五十一)
  • 自主采集高质量三维重建数据集指南:面向3DGS与NeRF的图像与视频拍摄技巧【2025最新版!!】
  • 活动回顾 | 「招商大脑 · 运营引擎」解码大数据招商与智慧园区运营新模式
  • Qt -DFS可视化
  • 91.首次使用Maui的体验与建议 C#例子 Maui例子
  • 系统思考:局部最优与全局失衡
  • windows远程服务器数据库的搭建和远程访问(Mysql忘记密码通过Navicat连接记录解密密码)
  • 量化交易之数学与统计学基础2.3——线性代数与矩阵运算 | 线性方程组
  • 加速LLM大模型推理,KV缓存技术详解与PyTorch实现
  • 车辆检测新突破:VFM-Det 如何用大模型提升识别精度
  • 解放日报:服务国家战略,加快建成科技创新高地
  • 金砖国家外长会晤落幕,外交部:发出了反对单边霸凌行径的“金砖声音”
  • 莫名的硝烟|“我们最好记住1931年9月18日这个日子”
  • 江西德安回应“义门陈遗址建筑被没收”:将交由规范的义门陈相关社会组织管理
  • 南京航空航天大学启动扁平化改革:管理岗规模控制在20%,不再统一设科级机构
  • 五月院线片单:就看五一档表现了