乐闻世界logo
搜索文章和话题

面试题手册

如何保护 WebSocket 连接的安全性?

在生产环境中保护 WebSocket 连接需要多层次的安全措施。以下是关键的安全实践:1. 使用 WSS(WebSocket Secure)强制使用加密连接:// 始终使用 wss:// 而不是 ws://const ws = new WebSocket('wss://example.com/socket');// 验证证书const ws = new WebSocket('wss://example.com/socket', { rejectUnauthorized: true // 拒绝无效证书});WSS 的优势:数据传输加密(TLS/SSL)防止中间人攻击保护敏感信息不被窃听2. 身份验证和授权连接时验证// 在握手时传递认证令牌const ws = new WebSocket(`wss://example.com/socket?token=${authToken}`);// 或在连接建立后发送认证消息ws.onopen = () => { ws.send(JSON.stringify({ type: 'auth', token: authToken }));};服务器端验证// 验证 JWT 令牌function validateConnection(token) { try { const decoded = jwt.verify(token, SECRET_KEY); return decoded.userId; } catch (error) { return null; }}// 握手时验证wss.on('connection', (ws, req) => { const token = req.url.split('token=')[1]; const userId = validateConnection(token); if (!userId) { ws.close(1008, 'Unauthorized'); return; } // 认证成功,继续处理});3. Origin 头部验证防止跨站 WebSocket 劫持(CSWSH):wss.on('connection', (ws, req) => { const origin = req.headers.origin; const allowedOrigins = ['https://yourdomain.com', 'https://app.yourdomain.com']; if (!allowedOrigins.includes(origin)) { ws.close(1003, 'Unsupported Data'); return; } // 允许连接});4. 速率限制和节流防止消息洪泛和 DoS 攻击:const rateLimiter = new Map();function checkRateLimit(userId) { const now = Date.now(); const userLimit = rateLimiter.get(userId); if (!userLimit) { rateLimiter.set(userId, { count: 1, resetTime: now + 60000 }); return true; } if (now > userLimit.resetTime) { rateLimiter.set(userId, { count: 1, resetTime: now + 60000 }); return true; } if (userLimit.count >= 100) { // 每分钟最多100条消息 return false; } userLimit.count++; return true;}wss.on('connection', (ws, req) => { ws.on('message', (message) => { if (!checkRateLimit(userId)) { ws.send(JSON.stringify({ type: 'error', message: 'Rate limit exceeded' })); return; } // 处理消息 });});5. 输入验证和消息过滤验证所有传入消息:function validateMessage(message) { const data = JSON.parse(message); // 验证消息结构 if (!data.type || typeof data.type !== 'string') { return false; } // 验证消息类型 const allowedTypes = ['chat', 'ping', 'auth']; if (!allowedTypes.includes(data.type)) { return false; } // 验证数据大小 if (JSON.stringify(data).length > 10240) { // 10KB 限制 return false; } // 验证内容(防止 XSS) if (data.content && /<script|javascript:|onerror=/i.test(data.content)) { return false; } return true;}ws.on('message', (message) => { if (!validateMessage(message)) { ws.close(1007, 'Invalid frame payload data'); return; } // 处理有效消息});6. 连接超时管理设置合理的超时时间:// 服务器端超时设置const server = http.createServer();const wss = new WebSocket.Server({ server, clientTracking: true, perMessageDeflate: false});// 设置 ping/pong 超时wss.on('connection', (ws) => { ws.isAlive = true; ws.on('pong', () => { ws.isAlive = true; });});// 定期检查连接状态const interval = setInterval(() => { wss.clients.forEach((ws) => { if (ws.isAlive === false) { return ws.terminate(); } ws.isAlive = false; ws.ping(); });}, 30000);wss.on('close', () => { clearInterval(interval);});7. 日志和监控记录安全相关事件:const securityLogger = { logConnection: (userId, ip, userAgent) => { console.log(`[SECURITY] Connection from ${ip} - User: ${userId} - UA: ${userAgent}`); }, logUnauthorized: (ip, reason) => { console.warn(`[SECURITY] Unauthorized connection attempt from ${ip} - Reason: ${reason}`); }, logSuspiciousActivity: (userId, activity) => { console.error(`[SECURITY] Suspicious activity from user ${userId}: ${activity}`); }};8. 网络层安全防火墙和负载均衡器配置:限制连接来源 IP设置最大连接数启用 DDoS 防护配置 Web 应用防火墙(WAF)安全检查清单[ ] 使用 WSS 加密连接[ ] 实施身份验证机制[ ] 验证 Origin 头部[ ] 实现速率限制[ ] 验证所有输入消息[ ] 设置连接超时[ ] 记录安全事件日志[ ] 定期更新依赖库[ ] 进行安全审计和渗透测试
阅读 0·2月18日 21:30

如何优化 Maven 构建速度?有哪些构建优化策略?

Maven 构建优化是提高项目构建速度和效率的重要手段,特别是在大型项目和持续集成环境中。通过合理的配置和优化策略,可以显著减少构建时间。构建优化策略:并行构建(Parallel Build):Maven 支持多线程并行构建,利用多核 CPU 加速构建过程:mvn clean install -T 4 # 使用 4 个线程mvn clean install -T 1C # 每个核心使用 1 个线程增量构建(Incremental Build):Maven 默认只重新编译修改过的文件,但可以通过以下方式优化:使用 maven-compiler-plugin 的增量编译功能配置 useIncrementalCompilation 参数跳过不必要的阶段:mvn clean install -DskipTests # 跳过测试mvn clean install -Dmaven.test.skip=true # 跳过测试编译和执行mvn clean install -Dcheckstyle.skip=true # 跳过代码检查优化依赖下载:使用国内镜像加速下载:<mirrors> <mirror> <id>aliyun-maven</id> <mirrorOf>central</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror></mirrors>配置本地仓库缓存策略使用离线模式:mvn -o clean install优化插件配置:禁用不必要的插件:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration></plugin>配置插件并行执行使用插件的最小必要配置使用构建缓存:配置 Maven 构建缓存目录使用持续集成工具的缓存功能配置 ~/.m2/repository 的缓存策略优化测试执行:并行执行测试:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <parallel>methods</parallel> <threadCount>4</threadCount> </configuration></plugin>使用测试分组和分类跳过慢速测试多模块项目优化:使用 -pl 参数构建特定模块:mvn clean install -pl module-a -am合理划分模块粒度使用 Reactor 优化构建顺序性能监控和分析:使用构建分析工具:mvn clean install -X # 启用调试模式mvn help:evaluate -Dexpression=project.version # 评估表达式分析依赖树:mvn dependency:treemvn dependency:analyze使用 Maven Profiler:安装 Maven Profiler 插件分析构建瓶颈识别慢速插件和目标最佳实践:在父 POM 中统一管理插件配置定期更新插件版本,获取性能优化使用 Profile 区分不同环境的构建配置在 CI/CD 流程中启用构建缓存监控构建时间,持续优化避免在构建过程中执行不必要的操作使用轻量级的测试框架优化资源文件处理CI/CD 环境优化:使用 Docker 镜像缓存依赖配置 CI 工具的构建缓存使用增量构建策略并行执行独立的构建任务预热构建环境通过以上优化策略,可以将 Maven 构建时间减少 30%-70%,显著提高开发效率和 CI/CD 流程的速度。
阅读 0·2月18日 21:30

SQLite 在移动开发中的应用和最佳实践是什么?

SQLite 在移动开发中有广泛的应用和特定的最佳实践:SQLite 在移动开发中的优势轻量级:占用资源少,适合移动设备零配置:无需安装和配置数据库服务器本地存储:数据存储在设备本地,离线可用跨平台:iOS、Android、React Native 等都支持移动平台集成 // iOS (Swift) - 使用 SQLite import SQLite3 let dbPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/database.db" var db: OpaquePointer? if sqlite3_open(dbPath, &db) == SQLITE_OK { // 数据库打开成功 } // Android (Kotlin) - 使用 SQLite class DatabaseHelper(context: Context) : SQLiteOpenHelper(context, "database.db", null, 1) { override fun onCreate(db: SQLiteDatabase) { db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)") } override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { db.execSQL("DROP TABLE IF EXISTS users") onCreate(db) } }移动应用数据库设计最佳实践简化表结构:避免过度规范化,减少 JOIN 操作使用索引:为常用查询字段创建索引批量操作:使用事务批量插入数据分页加载:使用 LIMIT 和 OFFSET 分页查询性能优化技巧 // Swift - 使用事务批量插入 sqlite3_exec(db, "BEGIN TRANSACTION", nil, nil, nil) for user in users { let sql = "INSERT INTO users (name) VALUES ('\(user.name)')" sqlite3_exec(db, sql, nil, nil, nil) } sqlite3_exec(db, "COMMIT", nil, nil, nil) // Kotlin - 使用预编译语句 val stmt = db.compileStatement("INSERT INTO users (name) VALUES (?)") users.forEach { user -> stmt.clearBindings() stmt.bindString(1, user.name) stmt.executeInsert() }数据同步策略增量同步:只同步变更的数据时间戳标记:使用 updated_at 字段跟踪变更冲突解决:实现冲突检测和解决机制后台同步:在后台线程执行同步操作离线支持本地缓存:将服务器数据缓存到本地 SQLite离线队列:将离线操作存储在队列中,在线时同步数据合并:实现本地和服务器数据的合并逻辑数据安全 // iOS - 使用 SQLCipher 加密 let key = "encryption_key".data(using: .utf8) sqlite3_key(db, key, Int32(key!.count)) // Android - 使用 SQLCipher SQLiteDatabase.loadLibs(context) val db = SQLiteDatabase.openOrCreateDatabase(dbPath, "encryption_key", null)数据库版本管理 // Android - 数据库升级 override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { if (oldVersion < 2) { db.execSQL("ALTER TABLE users ADD COLUMN email TEXT") } if (oldVersion < 3) { db.execSQL("CREATE INDEX idx_email ON users(email)") } }常见问题解决数据库锁定:使用 WAL 模式提高并发性能问题:使用 EXPLAIN QUERY PLAN 分析查询内存泄漏:及时关闭数据库连接和游标数据丢失:定期备份数据库ORM 框架选择iOS:Core Data、Realm、GRDBAndroid:Room、Realm、GreenDAOReact Native:react-native-sqlite-storage、WatermelonDBSQLite 是移动应用本地数据存储的首选方案,掌握其最佳实践对移动开发者至关重要。
阅读 0·2月18日 21:29

Maven 资源过滤是什么?如何使用资源过滤管理多环境配置?

Maven 资源过滤(Resource Filtering)是 Maven 提供的一种机制,允许在构建过程中动态替换资源文件中的变量。这个功能对于管理不同环境的配置非常有用。资源过滤的基本原理:Maven 在构建过程中会扫描资源文件(如 properties、xml、yml 文件),将其中包含的 ${variable} 形式的变量替换为 POM 文件中定义的属性值。配置资源过滤:在 POM 中启用资源过滤:<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> </resource> </resources></build>定义属性变量:<properties> <database.url>jdbc:mysql://localhost:3306/mydb</database.url> <database.username>root</database.username> <database.password>password</database.password> <app.version>1.0.0</app.version></properties>在资源文件中使用变量:# application.propertiesdatabase.url=${database.url}database.username=${database.username}database.password=${database.password}app.version=${app.version}结合 Profile 使用资源过滤:<profiles> <profile> <id>dev</id> <properties> <env>dev</env> <database.url>jdbc:mysql://dev-db:3306/mydb</database.url> </properties> </profile> <profile> <id>prod</id> <properties> <env>prod</env> <database.url>jdbc:mysql://prod-db:3306/mydb</database.url> </properties> </profile></profiles>资源过滤的高级用法:多资源目录配置:<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> <resource> <directory>src/main/static</directory> <filtering>false</filtering> </resource> </resources></build>使用外部属性文件:<build> <filters> <filter>src/main/filters/${env}.properties</filter> </filters> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources></build>测试资源过滤:<build> <testResources> <testResource> <directory>src/test/resources</directory> <filtering>true</filtering> </testResource> </testResources></build>注意事项:资源过滤会增加构建时间,只对需要的文件启用过滤避免在二进制文件(如图片、jar 包)上启用过滤使用 Profile 区分不同环境的配置敏感信息(如密码)应该使用环境变量或加密存储在 CI/CD 流程中使用 -D 参数传递动态属性最佳实践:使用 @variable@ 或 ${variable} 格式,避免与 Spring 等框架的占位符冲突在父 POM 中统一管理资源过滤配置使用 Maven 的默认分隔符 ${},也可以自定义分隔符定期检查过滤后的文件,确保变量替换正确资源过滤是 Maven 管理多环境配置的重要手段,能够显著简化配置管理工作。
阅读 0·2月18日 21:29

Maven 的构建生命周期有哪些阶段?如何使用 Maven 命令执行构建?

Maven 的构建生命周期(Build Lifecycle)是一系列有序的阶段(Phase),每个阶段代表构建过程中的一个步骤。Maven 定义了三套相互独立的生命周期:clean、default 和 site。1. Clean 生命周期:用于清理项目,包含三个阶段:pre-clean:执行清理前的工作clean:删除上一次构建生成的文件(target 目录)post-clean:执行清理后的工作2. Default 生命周期:这是最常用的生命周期,包含约 20 个阶段,主要阶段包括:validate:验证项目是否正确,所有必要信息是否可用compile:编译项目的源代码test:使用合适的单元测试框架测试编译后的源代码package:将编译后的代码打包成可分发的格式(JAR、WAR 等)integration-test:在集成环境中处理和发布包verify:运行检查验证包是否有效且符合质量标准install:将包安装到本地仓库,供本地其他项目使用deploy:将最终的包复制到远程仓库,供其他开发者和项目共享3. Site 生命周期:用于生成项目站点文档,包含:pre-site:执行生成站点前的工作site:生成项目站点文档post-site:执行生成站点后的工作site-deploy:将生成的站点部署到服务器生命周期执行规则:执行某个阶段时,其之前的所有阶段都会自动执行不同生命周期之间相互独立,执行一个生命周期不会影响其他生命周期可以通过 mvn phase 命令执行特定阶段,如 mvn clean install实际应用:开发阶段:mvn compile 编译代码测试阶段:mvn test 运行测试打包阶段:mvn package 打包应用本地安装:mvn install 安装到本地仓库完整构建:mvn clean package 清理并打包部署:mvn deploy 部署到远程仓库理解 Maven 生命周期对于自动化构建、持续集成和项目部署至关重要。
阅读 0·2月18日 21:29

Maven 的依赖传递性是如何工作的?如何解决依赖冲突?

Maven 的依赖传递性是指当一个项目依赖另一个项目时,会自动传递获取该项目的依赖。这种机制可以简化依赖管理,但也可能导致依赖冲突和版本不一致的问题。依赖传递规则:最短路径优先:如果存在多个版本的依赖,Maven 会选择依赖路径最短的版本。例如:A→B→C(v1.0) 和 A→D→C(v2.0),如果 A→B 的路径更短,则选择 v1.0。声明顺序优先:当依赖路径长度相同时,Maven 会选择在 pom.xml 中先声明的版本。依赖范围影响传递:只有 compile 范围的依赖会传递,test 和 provided 范围的依赖不会传递。依赖冲突解决方案:使用 <exclusions> 标签排除不需要的传递依赖:<dependency> <groupId>com.example</groupId> <artifactId>example-lib</artifactId> <version>1.0.0</version> <exclusions> <exclusion> <groupId>org.conflict</groupId> <artifactId>conflict-lib</artifactId> </exclusion> </exclusions></dependency>使用 <dependencyManagement> 统一管理依赖版本:<dependencyManagement> <dependencies> <dependency> <groupId>org.conflict</groupId> <artifactId>conflict-lib</artifactId> <version>2.0.0</version> </dependency> </dependencies></dependencyManagement>直接声明需要的版本,覆盖传递依赖的版本。最佳实践:定期使用 mvn dependency:tree 命令查看依赖树,识别潜在的冲突使用 mvn dependency:analyze 分析未使用和声明的依赖在父 POM 中使用 dependencyManagement 统一管理版本避免使用 SNAPSHOT 版本依赖,除非是开发环境对于大型项目,考虑使用 BOM(Bill of Materials)管理依赖版本
阅读 0·2月18日 21:28