十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

奇安信秋招前端笔试复盘:安全厂商考点全解析

奇安信秋招前端笔试复盘:安全厂商考点全解析 2020奇安信秋招前端方向试卷2 复盘安全厂商的前端笔试题到底在考什么又到了秋招季后台有不少同学在问奇安信的前端笔试题。刚好去年2020秋天我完整走了一遍奇安信的校招流程笔试、技术面、HR面一个没落最后也顺利拿了Offer。最近整理笔记翻出当时做的这套前端方向试卷2对着答案和后续面试追问重新过了一遍发现很多题目放到今天依然有参考价值。趁热打铁把这套试卷的完整解题思路、考察意图和踩坑记录整理出来给准备投递安全类互联网公司前端岗的同学做个参照。先说说这套试卷的整体感受奇安信作为安全行业的头部厂商前端笔试题并没有刻意去考渗透测试、漏洞挖掘这类安全工程师才需要掌握的硬核内容而是把安全思维渗透到了前端基础、网络协议、工程化这些常规考点里。整张卷子大概覆盖了JavaScript语言特性、浏览器工作原理、HTTP与网络安全、前端工程化与框架、算法与逻辑思维五个大方向题型以选择、简答和编程题为主题量适中但广度不低想要拿高分并不容易。下面我按题型模块拆解把每道题背后的考点逻辑和正确答题姿势都说清楚。即便你今年才准备投递把这份题解吃透再去刷其他安全厂商的笔试题会轻松很多。1. 整体设计与思路拆解安全厂商前端笔试的出题逻辑开始逐题分析前先聊点务虚但对备考很有用的事为什么奇安信会出这样的卷子它的出题人和普通互联网大厂的前端笔试思路有什么不同1.1 五个考察方向的权重分配从我拿到的这版试卷来看题目分布大致如下考察方向题型载体大致占比核心考察目标JavaScript语言特性选择题手写代码25%语言基本功是否扎实浏览器与网络选择题简答题20%前端运行环境理解深度网络安全简答题场景题15%安全敏感度与风险意识框架与工程化简答题配置题20%工程落地能力算法与逻辑编程题20%编码基本功与逻辑思维这个分布其实很有代表性。普通电商、内容平台的笔试题里安全方向占比可能只有5%左右顶多考一道XSS基础概念题。但奇安信把安全相关的考察提到了15%的权重而且不是孤立地考而是把安全问题放在真实业务场景里让你分析——比如给你一段有漏洞的代码问你如何修复。1.2 为什么要这么设计我后来入职后和当时出题的前端Leader聊过他的原话大意是前端岗位在安全公司不仅是做页面还要做安全产品的控制台、可视化大屏、数据展示这些场景对前端工程师的安全意识要求比普通业务线高得多。想想也确实如此。奇安信的产品线很多是安全运营平台前端要处理大量敏感数据展示漏洞详情、攻击溯源、威胁情报这类信息。如果前端工程师自己都不了解XSS、CSRF、点击劫持的原理写出来的控制台本身就可能是安全隐患。所以笔试题里反复出现这类题目本质上是在筛选“有安全思维的前端工程师”而不是单纯考你会不会写页面。这给了我们一个明确的备考方向:投递安全类公司的前端岗位除了常规的八股文和算法刷题一定要额外补充Web安全的基础知识重点是XSS、CSRF、CSP、同源策略、跨域方案这些和前端强相关的领域。2. 核心考点逐题解析JavaScript与浏览器原理这个模块是整张卷子的得分基础也是区分度比较高的部分。选择题看起来简单但很多选项都在考容易混淆的概念。2.1 变量提升与闭包经典题目里的细节陷阱试卷第一道选择题大概是这样的给出以下代码问输出结果是什么。for (var i 0; i 5; i) { setTimeout(function () { console.log(i); }, 0); }这个题几乎是前端笔试的“开场白”了答案是连续输出5个5。考点很清晰var声明的变量没有块级作用域循环结束后全局作用域里i的值已经是5所有setTimeout回调执行时访问的都是同一个i。但关键在于这道题往往是连环问。后面会追问如何改成输出0、1、2、3、4这里就有几种答法最简单直接的方式是把var改成let利用块级作用域为每次循环绑定独立的值。也可以用IIFE立即执行函数包裹setTimeout把i作为参数传入形成闭包。还可以用bind方法传参setTimeout(console.log.bind(null, i), 0)。答题时建议把三种方式都写出来并各用一句话说明原理。这比只写一种答案更能体现对闭包作用域的理解深度面试官后续追问的空间也更大。2.2 事件循环机制输出顺序题要画图作答另一道比较有代表性的题目是考察事件循环的console.log(1); setTimeout(function () { console.log(2); }, 0); Promise.resolve().then(function () { console.log(3); }); console.log(4);正确输出顺序是1、4、3、2。这道题考的是宏任务与微任务的执行顺序同步代码先执行微任务在本次事件循环末尾执行宏任务在下一轮事件循环执行。我的答题建议是遇到这类题不要只在脑子里过一定要在草稿纸上画出任务队列的变化过程。先写同步代码的执行顺序再分别标注宏任务队列和微任务队列中新增了什么最后模拟事件循环的调度过程。画完之后答案基本不会错。当时这个模块还考了原型链的查找规则、this指向的四种绑定方式、与的隐式转换规则等。这些都属于前端八股文的高频考点没有太多技巧就是要把基础概念吃透。我在准备阶段把MDN上关于JavaScript继承、类型转换、作用域的文档重新过了一遍再配合刷题效果比直接背面试题集要好得多。2.3 浏览器缓存与渲染机制安全厂商同样重视页面性能浏览器相关的题目里有一道关于缓存策略的分析题要求简述强缓存和协商缓存的区别以及对应的HTTP头字段。这道题本身不难但考察范围很广。完整的回答应该包括强缓存由Cache-Control和Expires控制命中时不会向服务器发送请求。协商缓存由Last-Modified/If-Modified-Since和ETag/If-None-Match控制需要向服务器发送请求确认资源是否变更。两者的关系是强缓存优先于协商缓存强缓存未命中时才可能走协商缓存。实际项目中静态资源JS、CSS、图片通常设置长缓存时间配合文件名hash实现更新HTML页面通常设置为协商缓存或禁用缓存。这题我后面在面试中被问到过变体如果强缓存和协商缓存同时存在服务器返回304时浏览器从哪里读取资源答案是浏览器会从本地缓存中读取资源304只是一个状态通知并不携带资源实体。浏览器渲染机制则考了回流与重绘的区别以及两者的性能差异。答题时可以举具体的触发场景改变元素的宽度、高度、位置会引发回流改变颜色、背景、可见性只会触发重绘。优化思路包括批量修改DOM、使用display: none离线操作、用transform代替位置动画等。这个考点虽然常见但在安全产品的可视化大屏场景中非常实用因为大屏页面往往有大量实时刷新的数据图表对渲染性能要求很高。3. 前端安全专项XSS、CSRF与CSP的完整答题模板这是我当时答卷里比较有特色、也是奇安信这类安全厂商相对更看重的板块。这里我结合卷面题目把完整答题套路整理出来。3.1 XSS跨站脚本攻击从危害到防御的完整链路试卷里有一道简答题什么是XSS攻击简述主要类型及防御措施。这道题由于是安全厂商出的我建议不要只答概念要按“原理、分类、危害、防御”四个层次展开首先是原理。XSS的核心是攻击者把恶意脚本注入到网页中在用户浏览器端执行。由于浏览器无法区分脚本来自开发者还是攻击者恶意脚本就获得了和合法脚本同等的执行权限。然后是分类。存储型XSS恶意脚本持久化存储在服务端所有访问页面的用户都可能中招、反射型XSS恶意脚本通过URL参数反射回页面需要诱导用户点击恶意链接、DOM型XSS通过修改页面DOM节点形成的XSS纯前端安全问题服务端无法感知。接着是危害。盗取用户Cookie窃取会话、伪造用户操作、钓鱼攻击、传播恶意代码等。最后是防御。这是关键拿分点需要答全面:输入过滤对用户输入进行白名单校验转义HTML标签、属性、URL中的特殊字符。输出编码在将数据插入HTML页面时根据上下文HTML标签内、属性内、JavaScript内选择合适的编码方式。使用CSP内容安全策略限制页面资源的加载来源即使脚本被注入也无法执行这是纵深防御的关键手段。HttpOnly Cookie将Cookie标记为HttpOnlyJavaScript无法读取有效缓解会话劫持风险。我当时在答这题时额外补充了Vue和React框架层面的注意事项Vue模板默认会转义插值内容v-html指令则会跳过转义直接渲染原始HTML使用时需要确保内容可信React中dangerouslySetInnerHTML同理。这些细节能让面试官感受到你不仅懂安全理论还有实际项目中的安全意识。3.2 CSRF跨站请求伪造校验Referer还不够另一道安全题是CSRF的攻击原理是什么如何防御CSRF的答题要点是攻击者诱导用户在已登录的浏览器中发出伪造的跨站请求由于请求携带用户的Cookie尤其是未启用SameSite属性时服务端无法判断请求是否由用户主动发起。防御措施可以从这几个层面答使用CSRF Token在页面表单中嵌入服务端生成的随机Token提交请求时校验Token是否匹配。校验Referer/Origin字段拒绝来源不明的跨站请求。设置SameSite Cookie属性Lax模式可以阻止跨站请求携带CookieStrict模式则完全禁止跨站携带。双重Cookie验证在请求中附带Cookie中的随机值和自定义请求头中的值服务端比对是否一致。特别提示一下奇安信这类安全公司的笔试和面试中你答出“只校验Referer不可靠”会是加分项。原因很简单Referer在某些场景下会被浏览器省略或篡改比如从HTTPS页面跳转到HTTP页面时浏览器不会发送Referer头。这种防御属于降低安全等级的做法仅作为辅助手段。3.3 同源策略与跨域方案越基础越要说得准同源策略几乎是所有安全题的基础。试卷里考了一道判断题浏览器同源策略中判断两个URL是否同源需要满足哪些条件答案是协议、域名、端口三个全部相同。现代浏览器对同源策略的管理其实有细化的地方我把答题时用到的对照表整理出来跨域行为是否被同源策略限制说明Cookie读取视同源定义而定早期按域名和路径判断现在逐步收紧DOM访问限制iframe跨域时无法访问对方DOMAJAX请求发送不限制请求可以发出但读取响应被限制AJAX响应读取限制受CORS机制管控localStorage/sessionStorage限制完全隔离CSS/JS/图片资源加载不限制通过link、script、img标签加载跨域解决方案则考了CORS、JSONP、代理转发、postMessage以及nginx反向代理等。对于安全厂商的笔试建议重点展开CORS的预检机制非简单请求会先发送一个OPTIONS请求服务端确认允许跨域后浏览器才会发送实际请求。能够说清楚预检请求的触发条件和响应头配置这题基本就是满分水平。4. 框架与工程化Vue源码原理和安全配置实践奇安信前端工程师日常工作大量使用Vue笔试试卷中框架和工程化的占比不算低而且很看重“能不能真正理解框架原理并解决工程问题”。4.1 响应式原理从数据变化到视图更新框架相关的简答题最核心的一道是简述Vue 2的响应式原理以及Vue 3相比Vue 2的改进。Vue 2部分要从这几个环节讲清楚数据初始化遍历data对象的属性用Object.defineProperty将它们转为getter/setter。依赖收集组件渲染过程中访问数据时触发getter将当前watcher添加到该属性的依赖列表中。派发更新数据变化时触发setter通知依赖列表中所有watcher执行更新最终触发视图渲染。Vue 3部分则要提到改用Proxy实现响应式可以拦截对象属性的添加、删除以及数组索引变化等解决了Vue 2中无法通过this.$set监听新增属性、数组变更检测不完整等痛点同时配合ref和reactive的API设计让响应式系统的使用更灵活。进阶答题时可以补充Vue 3的Proxy代理是懒代理即访问到某个层级的对象时才对该层级做代理因此初始化性能比Vue 2的递归遍历要好。这个点说明你读过源码相关内容而不是只背概念在面试中很容易引起面试官的好感。4.2 构建工具与代码规范安全公司也在意依赖安全工程化部分考了一道Webpack配置题如何将静态资源开启长缓存、如何做代码分割。这里就不重复基础配置了重点说一个我在实际答题时主动补充、后来被面试官当场追问的点依赖安全与供应链攻击。奇安信作为安全公司对第三方依赖的安全非常敏感。前端项目会使用npm或yarn安装大量第三方包如果某个依赖被投毒恶意代码通过正常发布流程混入开源包影响面可能是整个产品线。我在回答时提到生产环境构建前应执行npm audit检查已知漏洞并在CI/CD流水线中接入依赖扫描工具同时建议使用锁文件(package-lock.json或yarn.lock)固定依赖版本配合私有npm镜像仓库对依赖进行统一管控。这个额外补充其实超出了普通前端工程师的认知范围但在安全厂商的场景下特别加分建议准备面试的同学一定要有这方面的知识储备。4.3 生命周期与组件通信一个高频简答的完整答法试卷里还有一道Vue生命周期相关的简答题要求说明created和mounted的区别。参考答案可以分为三个层次执行时机不同created在实例创建完成后立即调用此时数据和事件已初始化但DOM还未挂载mounted在模板渲染并将真实DOM挂载到页面后调用。可用能力不同created中不能访问this.$elmounted中可以操作真实的DOM节点。使用场景不同created适合做接口数据拉取、初始化非DOM依赖的数据mounted适合做需要依赖DOM 的操作比如初始化图表、绑定第三方库事件等。组件通信方面我建议把以下方式整理成答题清单props和$emit父子组件、$refs父访问子实例、provide/inject跨层级依赖注入、eventBus非父子组件通信、Vuex/Pinia状态管理。每个都写一句使用场景面试时按需展开即可。5. 编程题实录从思路推导到完整AC代码这套试卷的编程题有两道一道是算法题一道是场景题。下面是我当时写的解题过程和最终AC代码附上完整的思路推导。5.1 算法题数组中的第K个最大元素题目描述给定一个未排序的整数数组找出其中第K个最大的元素。例如数组[3,2,1,5,6,4]K2时返回5。看到这道题最先想到的当然是先排序再取下标时间复杂度是O(n log n)。不过笔试环境里仅仅这样写并不能体现编码能力我选择了用快速选择算法平均时间复杂度可以降到O(n)。快速选择的思想和快速排序很像每次选一个基准值pivot把数组分为小于基准值和大于基准值的两部分然后根据基准值在排序后数组中的位置决定继续在左半边还是右半边查找。/** * param {number[]} nums * param {number} k * return {number} */ const findKthLargest function (nums, k) { const targetIndex nums.length - k; const quickSelect (left, right) { // 基准值取最右侧元素 const pivot nums[right]; let storeIndex left; // 将小于等于pivot的元素移到左侧 for (let i left; i right; i) { if (nums[i] pivot) { [nums[storeIndex], nums[i]] [nums[i], nums[storeIndex]]; storeIndex; } } // 将pivot放到正确位置 [nums[storeIndex], nums[right]] [nums[right], nums[storeIndex]]; if (storeIndex targetIndex) { return nums[storeIndex]; } else if (storeIndex targetIndex) { return quickSelect(storeIndex 1, right); } else { return quickSelect(left, storeIndex - 1); } }; return quickSelect(0, nums.length - 1); };写代码时要注意几个易错点边界条件是left right还是left right基准值交换的时机以及在查找右半边时storeIndex 1而不是storeIndex否则可能死循环。我当时提交后特意用[3,3,3,3,3]这种全重复数组做了自测确保算法不会因为值相等而异常。5.2 场景题并发请求控制器的实现编程题第二题比较有意思考察的是实际工程中很常见的场景实现一个并发请求控制器限制同时只能有limit个请求在执行其余请求排队等待。这道题的考点是手写Promise并发控制、异步队列管理、错误处理。我当时给的解法如下/** * 并发请求控制器 * param {ArrayFunction} tasks - 每个任务是一个返回Promise的函数 * param {number} limit - 最大并发数 */ async function runWithConcurrency(tasks, limit) { const results new Array(tasks.length); let currentIndex 0; const worker async () { while (currentIndex tasks.length) { const index currentIndex; currentIndex; try { results[index] await tasks[index](); } catch (e) { results[index] e; } } }; const workerCount Math.min(limit, tasks.length); const workers []; for (let i 0; i workerCount; i) { workers.push(worker()); } await Promise.all(workers); return results; }这个实现的关键在于通过一个共享的currentIndex指针让每个worker空闲时都去取下一个待执行的任务而不是固定分配任务。这样即使某个任务执行得特别快也不会出现部分worker空转的情况整体吞吐量是最高的。错误处理上我用try/catch捕获每个任务的异常防止某个任务失败导致整个控制器中断。这是实际项目中非常重要但很多候选人在笔试时容易忽略的点。6. 高频问题与现场复盘题目之外的拿分关键最后整理几个当时笔试和后续面试中反复出现、但题目本身并没有直接考的延展问题。这些问题往往是面试官根据你的笔试卷面追问出来的提前准备好会很加分。6.1 简历项目和笔试题的联动追问我笔试时在安全相关的简答题里写到了CSP面试官就顺着追问你们的项目里如何配置CSP如果使用了style-src限制内联样式但页面里又用了动态计算的样式属性如何处理这个问题其实在考CSP的unsafe-inline和nonce机制。我答的是给合法的内联脚本和样式添加nonce属性并在CSP中配置nonce-xxx这样浏览器只允许带有正确nonce的内联内容执行。如果你对nonce机制不熟悉建议提前补一下这是CSP相关提问中最高频的深入问题之一。另一个追问方向来自工程化为什么代码分割能提升首屏加载速度我在笔试题中提到了动态import做路由懒加载面试官就让我解释动态import的底层实现原理。这已经从工程应用问到编译原理层面了如果答不上来不用慌如实说“这个我了解不深我目前的理解是……”然后给出你已知的部分至少能展示诚实和学习意愿。6.2 从错误答案中学到的排查思路我在这套试卷上有一个记忆深刻的失误一道关于隐式转换的选择题我判断错了[] ![]的结果。具体来看这个表达式的求值过程![]的结果是false空数组是truthy取反为false因此原式变成[] false按规范[]会先转成字符串然后 false之后布尔值转数字false变为0字符串变为数字0最终是0 0结果为true。整个过程涉及ToPrimitive、ToNumber、ToBoolean三层隐式转换规则。当初我在考场上心里想的是“数组不等于布尔值”结果就跳坑了。这种题目的价值不在于让你记住“结果为true”而是理解隐式转换的执行顺序。面试中考官会顺着问实际开发中如何避免这类隐式转换问题答案很简单统一使用减少类型转换带来的不确定性。6.3 考试时间分配与心态调整最后聊一个不那么技术、但同样影响成绩的话题时间分配。这套试卷题量不是特别大但简答题写起来很耗时。我当时的策略是选择题控制在20分钟以内遇到需要计算的题快速在草稿纸上推算不确定的先标记不纠结。简答题先列回答大纲用关键词提纲挈领再展开成完整句子。这样即使时间紧张每道题都有清晰的拿分要点。编程题留足40分钟以上。先写功能正确的基础版本再考虑优化。比如第K大元素可以先写排序版本保证AC再补充快速选择版本展示优化能力。预留10分钟检查。重点看选择题有没有看错选项、编程题边界条件是否都有处理。这个时间分配方案不一定适合所有人但核心原则可以复用越靠前的客观题越要控制时间编程题宁可写得朴素也要保证通过率简答题宁可结构清晰也不要在某一道题上过度堆砌字数。写在最后的个人体会整套卷子做下来我最深的感受是奇安信前端方向笔试题并没有在“难”上做文章而是更看重你是不是一个“基础扎实、思维严密、有安全意识”的工程师。如果你是准备校招的同学我的建议是不要只刷面试题而是把JavaScript语言规范、浏览器原理、Web安全这些基本功真正吃透。安全厂商给你的反馈往往不是“你刷题多”而是“你理解得深、表达得清楚、意识在线”。最后分享一个小技巧笔试结束后建议立刻把题目和你的答案记录下来。一方面是为了复盘另一方面是为了后续面试准备——奇安信的技术面会拿着你的笔试卷追问要是连自己当时写了什么、为什么这么写都说不清楚那才是真的亏大了。祝各位都能顺利拿到心仪的Offer。
返回列表