天天看點

「前端」2019.10 騰訊實習生一面

上來甩了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請求中

get

post

的差別

  • 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與安全相關的屬性:

「前端」2019.10 騰訊實習生一面

cookie的缺陷:

  • cookie太小,隻有4k左右
  • 過多的cookie會帶來巨大的性能浪費
  • 因為明文傳輸,是以安全性成問題,除非使用HTTPS

3. CSRF(跨站請求僞造)

這個問題可以說是本次面試的敗筆,本來是必會的知識,卻在這裡栽了跟頭。

跨站請求僞造在什麼情況下可能發生呢?

「前端」2019.10 騰訊實習生一面

從上圖可以看出,要完成一次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過期時間來做登入态保持,沒有辦法對請求作出驗證。

總結

準備不充分隻最主要的問題了,當時面試官打電話來問什麼時候可以面試的時候一時嘴快說了今天就行,沒有做足準備,過不了也很正常。最近學業實在繁忙,課程作業考試壓力挺大的。也就這樣吧,隻能繼續努力了。

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

繼續閱讀