Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第十五週網站前後端開發基礎測試參考解答 #5

Open
aszx87410 opened this issue Jul 4, 2019 · 2 comments
Open

第十五週網站前後端開發基礎測試參考解答 #5

aszx87410 opened this issue Jul 4, 2019 · 2 comments

Comments

@aszx87410
Copy link
Member

aszx87410 commented Jul 4, 2019

這個 Issue 主要是第十五週會出現的網站前後端開發基礎測試的參考解答。

原本在 Google 表單提交之後就會有參考解答可以看,但一來修改內容不太方便,二來有疑問也沒辦法馬上討論,所以最後就決定在 GitHub 也開一個 Issue 來講一下解答。

如果有任何問題歡迎在下面留言,解完有收穫或是有寫成心得筆記也歡迎分享在下面。

底下解答都是點開才會顯示的,不用怕被雷到。

Q1

有天小明來找你,跟你說:

欸欸,主管剛出了一個作業,跟我說要我寫一個 Todo list 的後端 API,要回傳代辦事項的列表,還要能新增、編輯以及刪除 todo。

但是有一個限制,主管要我只能用 GET 這個 HTTP Method 來實作!開玩笑,這怎麼可能嘛,新增要用到 POST,刪除要用到 DELETE,只用 GET 怎麼想都是不可能的,你說呢?

請問小明說得正確嗎?
如果你只能用 GET 寫一個 Todo list 的後端,你做得到嗎?如果做不到,原因為何?

點我看 Q1 解答

答案:做得到。

這一題想考的是「慣例」跟「限制」的差別。

之所以刪除動作會用 DELETE,是因為這是一種好習慣,而不是因為「必須要」這樣做。所以儘管你只有 GET 這個 method,你依然可以寫出新增、刪除以及編輯的功能,只是網址就會不符合 RESTful 的規則,大概會變成這樣:

  1. add_todo?id=xx
  2. edit_todo?id=xx&content=xx
  3. delete_todo?id=xx

總而言之,HTTP Method 的使用本來就不是強制的規範,這題希望讓大家理解的是這件事,不過能夠符合 method 的語義當然是最好的。

Q2

承上,如果變成只能用 POST 這個 method,做得到嗎?如果做不到,原因為何?

點我看 Q2 解答

第一題講解過了,做得到。

Q3

公司內部有一個 API 是拿來刪除文章的,只要把文章 id 用 POST 帶過去即可刪除。

舉例來說:POST https://lidemy.com/deletePost 並帶上 id=13,就會刪除 id 是 13 的文章。

公司前後端的網域是不同的,而且後端並沒有加上 CORS 的 header,因此小明認為前端用 ajax 會受到同源政策的限制,request 根本發不出去,所以前端沒辦法利用 ajax 呼叫這個 API 刪除文章。

請問小明的說法是正確的嗎?如果錯誤,請指出錯誤的地方。

點我看 Q3 解答

答案:錯誤。

這題考的是你對同源政策的理解程度。

首先,同源政策限制的對象有兩種,簡單請求跟非簡單請求,前者像是 GET 跟 POST(還必須沒有加上任何 custom header),後者像是 DELETE 之類的。這邊可以自己去找 MDN 的參考資料來看。

簡單請求跟非簡單請求的差別在於:

  1. 簡單請求限制的是「拿到 response」而不是「發出 request」,這是超級無敵重要的一點,但我想很多人都會搞混

  2. 非簡單請求會先發出一個 OPTIONS 的 request 去查看後端是否允許非同源的 request,如果不允許,則不會把請求發出去。舉例來說,使用 DELETE 方法就會先發出 OPTIONS 的 request,確認後端有帶 CORS 的 header 才會把 DELETE 的 request 發出去。

所以,以這題的狀況來說,儘管後端沒有加上 CORS 的 header,刪除文章的 request 依舊發的出去,只是前端的 JS 拿不到 response,然後 console 會出現錯誤。所以文章還是被刪掉了,只是前端不知道到底有沒有成功。

Q4

有天小明表示他對 XSS 的防禦方法不太理解,他說:

不是啊,幹嘛要 escape 字串,既然 XSS 的問題是因為可以執行 script,那我就直接把 <script> 標籤取代掉就好了,例如說:str_replace(“<script>”, “”, html),這樣就不能執行 JS 了,不就沒問題了嗎?

請問小明的說法是正確的嗎?如果錯誤,請指出錯誤的地方。

點我看 Q4 解答

答案:錯誤

這題考的是你對 XSS 的認知是否太薄弱。

的確,照小明的說法 <script> 會被封掉,但是如果攻擊者把標籤改成 <SCRIPT> 就可以繞過這個字串取代了。

而且就算改成無論大小寫都會被取代掉,我依然可以不用 script 標籤執行 JS,例如說 <img onerror="alert(1)" /> 也可以成功執行 XSS。

Q5

小明在學習到 SQL Injection 之後非常興奮,他說 SQL Injection 就是靠攻擊者傳入惡意字串與原本的 query 拼在一起導致攻擊成功,只要用 prepared statement,交給資料庫來處理這些惡意字串就好。

以 PHP 為例,就是像這樣:

$stmt = $mysqli->prepare(“SELECT * from Todos where id = ?”)
$stmt->bind_param("i", $id)
$stmt->execute()

這樣子就能防止 SQL Injection 了!

請問小明的說法是否正確?如果錯誤,請指出錯誤的地方。

點我看 Q5 解答

基本上是正確的,除非哪天 prepared statement 被發現漏洞。

Q6

在公司內部有一個留言板的系統,必須註冊才能留言,而且只有自己能夠刪除自己的文章。在前端的實作上為了確保不能刪除到別人的文章,只會在自己的文章旁邊顯示刪除按鈕。

而後端則是一個簡單的 API:DELETE /posts/:id。程式碼大概是長這樣的,就只是依據傳進來的 id 把文章給刪除掉:deletePost($id)

小明覺得這樣沒什麼問題,既然前端不會顯示刪除文章的按鈕,就不可能刪除到別人的文章。

請問小明的說法是正確的嗎?如果錯誤,請指出錯誤的地方。

點我看 Q6 解答

答案:錯誤

這題考的是你對前後端的理解是否正確。

前端歸前端,後端歸後端。任何人都可以發 request 到你的後端程式去,帶著任何的資料。

儘管你前端把按鈕藏起來,但沒人可以阻止我自己發 request 到後端。因為後端沒有做權限驗證,所以我只要自己發 request 過去,就可以刪除任何文章。

記住,後端的權限管理是一定要做的。在處理 CRUD 時要特別注意到權限管理這一塊,不要讓使用者能夠改到其他人的東西。

Q7

小明正負責寫一個專案,網址是:https://best-project.com 。這網站會需要用到公司網站某個檔案,裡面是一些使用者資料,例如說:https://lidemy.com/users.json ,小明直接點開這個網址,發現用瀏覽器可以看到內容,於是就說:

既然我用瀏覽器可以看得到內容,那用 Ajax 的時候也一定可以拿得到資料啦!我們來用 Ajax 拿資料吧!

請問小明的說法是正確的嗎?如果錯誤,請指出錯誤的地方。

點我看 Q7 解答

答案:錯誤

可以用瀏覽器直接打開網頁是一回事,但用 Ajax 又是另外一回事。我可以打開 Facebook.com,不代表我可以用 Ajax 拿到 Facebook.com 的內容。這完全是兩回事,是完全不相干的事情。

同源政策限制的是 Ajax,而不是你在瀏覽器上面直接造訪網站,這兩者是完全不同的。

因此這個網址的 Ajax 會受到同源政策的限制,可能拿得到也可能拿不到,要看後端有沒有帶 CORS header,所以小明說「一定也可以拿得到」是錯誤的。

Q8

公司要小明負責寫一個會員系統,小明在實作註冊與登入功能時,想起以前前輩教的事情,那就是在把密碼存入資料庫以前必須先經過 hash。

於是小明使用了 bcrypt,密碼在存入資料庫以前都會先使用 bcrypt 來做雜湊。

請問小明的做法是正確的嗎?如果錯誤,請指出錯誤的地方。

點我看 Q8 解答

答案:正確

bcrypt 是雜湊的演算法之一,大家要記得絕對不要存 plaintext 的密碼進資料庫喔!

Q9

小明寫了一段程式碼,希望能在網頁載入完成時執行一個 function:

function start() {
  console.log('網頁載入完成')
}

window.onload = start()

而小明在網站載入成功後打開 console,發現文字的確有被印出來。

請問小明的程式碼是否有問題?如果有的話,為什麼文字還是被印出來了?

點我看 Q9 解答

答案:有問題

這樣寫是代表要把 start 這個 function 執行後的結果傳給 window.onload,所以在網頁還沒載入好時其實就會執行 start()。

正確的寫法應該是 window.onload = start

Q10

小明在執行程式的時候出現了一個錯誤:Uncaught TypeError: Cannot read property 'selfId' of undefined,但百思不得其解,不知道是哪裡出了問題,以下是出錯的「部分」程式碼:

const result = list.filter(item =>
  item.parent.id === matches[0].parent.id &&
  item.parent.name === matches[0].parent.name &&
  item.selfId === homeData.selfId
).sort(
  (a, b) => a.typeId - b.typeId
);

根據你的推理,會出現這個錯誤的原因是什麼?

點我看 Q10 解答

這一題是我覺得最好玩的一題,考驗你對 JS 錯誤訊息的理解。

你可能會認為說:「不對吧,你很多資訊都沒有給齊,這題怎麼解?狀況很多吧!」

讓我來幫你解惑,首先你可能會答說:「homeData 上面可能沒宣告」,但如果是這種狀況,錯誤訊息就會是 ReferenceError: homeData is not defined,所以這種狀況可以排除,代表 homeData 一定有宣告。

同理,matches 也一定有宣告,不然錯誤訊息會不一樣。

再來,錯誤訊息告訴我們說:Cannot read property 'selfId' of undefined,代表我們試圖對一個 undefined 讀取 selfId 這個屬性。

出現 selfId 的是這行:item.selfId === homeData.selfId。

如果 item 是 undefined,前面 item.parent.id 時就會出錯,所以 item 是沒有問題的。

因此,會出現這個錯誤訊息的原因是 homeData 是 undefined。

@Lauviah0622
Copy link

Lauviah0622 commented Sep 25, 2020

如果 Q2 不行 Q3 是不是題目就不成立 XD

在解 Q4 有查到一個https://xss-game.appspot.com/自己第三關破關中還蠻有趣的

Q1 google 問卷上的解答是

HTTP method 雖然有這麼多種,但如果不管語義的話,依然可以用 GET 實作出所有的 API。例如說 GET delete.php?id=1 就可以實作刪除功能,GET new_todo.php?content=xxx 就可以實作新增 Todo 的功能等等(但可能字數會有限制)

這裡有點好奇,就去查說到底限制多少字數,結果查到了這篇,上面有講說每個瀏覽器限制的字數,可是基本上這些都是瀏覽器在 address bar 跟windows.location 跟 <a> tag 的限制,所以單純用 JS 發 request 應該是沒有限制。所以如果是利用 ajax 發送 GET 就算在 URL 上面帶一本資治通鑑理論上也是沒問題(?)

@aszx87410
Copy link
Member Author

如果 Q2 不行 Q3 是不是題目就不成立 XD

好像是這樣沒錯XD

在解 Q4 有查到一個https://xss-game.appspot.com/自己第三關破關中還蠻有趣的

這個第三期其實有給大家玩,第四期拿掉因為難度太高一堆人破不出來XDD

有關限制字數

基本上 HTTP protocol 沒限制沒錯,但是:

  1. 瀏覽器的 ajax 可能也有限制(要去翻 source code)
  2. 伺服器也有可能有限制(這我比較確定一點,但不能 100% 肯定)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants