「前端」2019.10 腾讯实习生面

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_26377547/article/details/102654782

上来甩了4道算法题,算法确实薄弱,整蒙了:

笔试部分

算法题1:
leetcode 283:https://leetcode-cn.com/problems/move-zeroes/submissions/

算法实现:

var moveZeroes = function(nums) {
    var sum = 0;
    var len = nums.length;
    for(let i=0;i<len;i++) {
        if(nums[i] === 0) {
            sum++;
            nums.splice(i, 1);
            i--;
        }
    }
    for(let i=0;i<sum;i++) {
        nums.push(0);
    }
    return nums;
};

算法题2:
leetcode 617:https://leetcode-cn.com/problems/merge-two-binary-trees/

算法实现:

var mergeTrees = function(t1, t2) {
    if(t1 === null) {
        return t2;
    } else if(t2 === null) {
        return t1;
    } else {
        t1.val = t1.val + t2.val;
        t1.left = mergeTrees(t1.left, t2.left);
        t1.right = mergeTrees(t1.right, t2.right);
        return t1;
    }
};

算法题3:
页面page的主函数入口在page.js,以下为其依赖树。
为了性能要求我们页面会组装一个combo请求:http://res.wx.qq.com/F.js,E.js,D.js,C.js,B.js,A.js,page.js,每个js文件都是用自运行匿名函数包裹起来,服务器端按顺序把js文件合并后返回。
请设计gen_url(requireTree),返回值会如上所示的combo url。
requireTree的数据结构如下页。

requireTree = {
  "name": "page.js",
  "require": [{
    "name": "A.js",
    "require": [{
      "name": "C.js",
      "require": [{
        "name": "F.js"
      }]
    }]
  }, {
    "name": "B.js",
    "require": [{
      "name": "D.js",
      "require": [{
        "name": "F.js"
      }]
    }, {
      "name": "E.js",
      "require": []
    }]
  }]
}

算法实现:
(待填)

算法题4:
leetcode 503:https://leetcode-cn.com/problems/next-greater-element-ii/solution/

算法实现:

var nextGreaterElements = function(nums) {
  var max = Number.MIN_SAFE_INTEGER;
  var len = nums.length;
  var res = [];
  var stack = [];
  if(!nums.length) {
    return [];
  }
  if(nums.length === 1) {
    return [-1];
  }
  nums.forEach((item, index) => {
    if(item > max) {
      max = item;
    }
  })
  var newNums = [];
  var loop = nums.concat(nums);
  var length = loop.length;
  for(let i=0; i<len; i++) {
	if(nums[i] === max) {
	  newNums.push(-1);
	  continue;
    }
    for(let j=i+1; j<length; j++) {
      if(loop[j]>nums[i]) {
        newNums.push(loop[j]);
        break;
      }
    }
  }
  return newNums;
};

面试部分

1. 请讲一讲http请求中getpost的区别

  • GET在浏览器回退时是无害的,而POST会再次提交请求。

  • GET产生的URL地址可以被Bookmark,而POST不可以。

  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。

  • GET请求只能进行url编码,而POST支持多种编码方式。

  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

  • GET请求在URL中传送的参数是有长度限制的,而POST没有。

  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

  • GET参数通过URL传递,POST放在Request body中。
    (上面是来自W3CSchool的答案)

除此之外,还有一些区别:

  • GET请求产生一个TCP数据包,而POST请求产生两个TCP数据包(分别发送header和body)。
  • POST请求在发送复杂请求或存在自定义请求头时会先发送一个OPTIONS请求到服务器获取服务器支持的请求方法。(为什么会发送OPTIONS请求可以看这篇文章:https://juejin.im/post/5cb3eedcf265da038f7734c4)

2. 了解过cookie与安全相关的属性吗?
详细的解答,包括其他的浏览器存储(localStorage、sessionStorage、IndexedDB等)移步:https://github.com/ljianshu/Blog/issues/25
cookie与安全相关的属性:
在这里插入图片描述
cookie的缺陷:

  • cookie太小,只有4k左右
  • 过多的cookie会带来巨大的性能浪费
  • 因为明文传输,所以安全性成问题,除非使用HTTPS

3. CSRF(跨站请求伪造)
这个问题可以说是本次面试的败笔,本来是必会的知识,却在这里栽了跟头。
跨站请求伪造在什么情况下可能发生呢?
在这里插入图片描述
从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:

  1. 登录受信任网站A,并在本地生成Cookie。
  2. 在不登出A的情况下,访问危险网站B。

看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:

  1. 你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
  2. 你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了…)
  3. 上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

如何防护CSRF?

  • 使用JSON API
    使用JavaScript发起AJAX请求是限制跨域的,并不能通过简单的<form> 表单来发送JSON,所以,通过只接收JSON可以很大可能避免CSRF攻击。
  • 加入HTTP Referer字段
    当用户通过黑客的网站向合法网站发起请求时,只能通过黑客的网站构造请求,这时验证HTTP Referer字段是指向黑客的网站的。若用户通过合法网站发送请求,则HTTP Referer是指向合法网站的,服务器端则可认为该请求合法。
  • 在请求地址中添加takon验证
    CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
    这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对。

4. 在你的项目中,你觉得最有意思的一个项目是哪个?
这个问题摆明了就是面试官想考我对项目的思考,然而我对项目实在没什么思考的,项目做的不好的地方自己感觉只有两点:

  1. 没有做特别多的安全防护,只简单防护了XSS(跨站脚本攻击)
  2. 没有很好的组织代码的架构(文件分类较乱,且路由组织存在重复)

面试官从第一个安全防护引出了cookie与安全相关的属性和CSRF两个问题,然后我只答出的cookie的部分安全属性。
安全部分后端其实是做了的,使用了token验证请求是否合法和登录态保持,但是前端在设计的过程中由于团队沟通问题,导致后端设计了token,而前端在完成了大部分之后才知道有token,最终前端只能通过设置cookie过期时间来做登录态保持,没有办法对请求作出验证。

总结

准备不充分只最主要的问题了,当时面试官打电话来问什么时候可以面试的时候一时嘴快说了今天就行,没有做足准备,过不了也很正常。最近学业实在繁忙,课程作业考试压力挺大的。也就这样吧,只能继续努力了。

人生如逆旅,我亦是行人。

猜你喜欢

转载自blog.csdn.net/qq_26377547/article/details/102654782