此份自我檢測目標:
給未來求職前的自己作為回頭複習ㄉ筆記
or(如果我寫到一半發懶)
直接想像自己在面試時被問到,我會怎麼回~
WEEK11
P1 你知道什麼是雜湊(Hash function)、你知道什麼是加密(Encryption)、你知道雜湊與加密的差別
如果使用者密碼直接被存入資料庫中,只要資料庫直接被偷看(像是在圖書館使用時上廁所忘了換頁),或用其他攻擊方式直接叫出密碼,使用者的資訊安全就會受到威脅,因此存在資料庫中密碼欄位的密碼最好不是原始的樣子。
雜湊和加密都是把原始的明碼輸入轉換成密碼,都是只要輸入字串和加密方法一樣,就可以得到一樣的密碼。
差別在加密是一對一,因此若知道加密規則和輸出結果,就可以回推出原本的明碼,是一對一的關係;但雜湊 (hash) 是多對一的關係,也就是雖然每次輸入都會得到同樣的輸出,但因為不止這組輸入會得到一樣的輸出,因此就算知道加密規則和結果,也無法回推原本是哪個字串,因此安全性又更高。
PHP 中雜湊的語法如下:
```
password_hash(<string>, <編碼方式>)
//可轉換成 hash ,建議存到預留 60 字元以上的欄位
password_verifty(<明文>, <hash>)
//對照兩者是否相同。
```
P1 你知道什麼是 SQL Injection 以及如何防範
SQL Injection 是在輸入的字串中夾帶 SQL 的語法,又因為字串拼接設計不良,夾帶進去的內容被當成 SQL 語法的一部份執行而導致的資安漏洞。以下舉個例子:
程式碼如下:
```
$sql = sprintf("INSERT INTO comments(username, content) VALUES('%s', '%s')", $_POST['username'], $_POST['content']);
```
只要我在 content 的欄位輸入 '), ('not_me', (select password from users));#
,就會變成這樣:
$sql = INSERT INTO comments(username, content) VALUES('me', ''), ('not_me', (select password from users));#')
因為 #
後面會變成附註,因此變成新增兩條留言,第二條的 username 和 content 附註,其中內容甚至可以叫出所有用戶的資料。超危險。
解決方法:使用 SQL 內建機制拼接
$sql =
// 這邊預留空間的方法是用問號 '?'
$stmt = $conn->prepare($sql) ;
// 先準備好
$stmt->bind_param('<拼接什麼>', $<變數1>, $<變數2>) ;
// 如果要拼接兩個字串,就用 'ss' ,整數的話就是 'i'
$result = $stmt->execute()
// 執行 query
// 接著用原本的判斷式檢測是否執行成功
$result = $stmt->get_result()
//這樣才算拿到結果
P1 你知道什麼是 XSS 以及如何防範
XSS 全名 Cross-Site Scripting
,也就是跨網站執行 JavaScript。例如顯示留言的地方的 HTML 如下:
<div class='content'><?php echo $row['content']?><div>
這時只要使用者輸入 html 或 JavaScript 語法,例如 <script>alert('hacked')</script>
,就會直接被解讀為程式碼的一部份並被執行。
防範方法:字元跳脫
函式 htmlspecialchars()
可將 html 的特殊符號轉換成純文字。
值得注意的是,因為資料庫儲存原始資料就好,因此建議在輸出處使用。另外,因為不知道攻擊會從哪裡來,因此建議所有輸出都使用字元跳脫。
P1 你知道為什麼儘管前端做了驗證,後端還是要再做一次驗證
因為前端的驗證只針對瀏覽器畫面上的驗證,但除此之外還有許多漏洞,例如不透過瀏覽器發 request 給後端即可繞過。通常簡單如「是否有東西漏填」這種驗證會給前端,而和資安相關的例如身分驗證則由後端負責。
P2 你知道什麼是 CSRF 以及如何防範
參考資料:
讓我們來談談 CSRF
[week 11] 資訊安全 - 雜湊與加密 & 常見攻擊:SQL Injection、XSS
CSRF 的全名是 是 Cross Site Request Forgery
(跨站請求偽造)。也被稱為 one-click attack 或 session riding。簡單來說就是「在不同 domain 下,偽造使用者本人發出的 request」。
平時登入網站後會得到一組 SESSION ,之後就算離開該網站,瀏覽器還是會幫你在 COOKIE 中保留 SESSION 一段時間。此時如果有個釣魚網站騙你在不知情的情況下,對該網站送出 Request (例如放在按鈕或圖片中),此時因為瀏覽器還留著你的 SESSION ,該網站以為是合法請求並接受,這樣一來釣魚網站就可以用你的身分在該網站進行操作。
不同層面的防範辦法
對使用者端來說,最好懂的就是隨時清空 SESSION,不過這就代表每次都要重新登入,很麻煩。
Server 端可以進行雙重驗證,像是輸入驗證碼就很直接,但每個動作都要輸入一次驗證碼有點麻煩,因此最好的方法是多加一層雙重認證。可以用表單中夾帶 CSRF token ,資料確認時也要保證其有被帶上才執行,產生和儲存都由 Server 端負責,但如果攻擊者先發出 request 就可破解;第二種方法是 Double Submit Cookie ,利用「cookie 只會從相同 domain 帶上來」的特性,把資料存在使用端,但只要攻擊者掌握任何 subdomain 就可破解;最後一種是由 Client 產生 token ,同時放到表單和 cookie 中。
瀏覽器方面, Chrome 也有提供 SameSite cookie 幫 cookie 加上一層驗證。
WEEK12
P1 你知道什麼是 SPA
Single Page Application
簡稱 SPA ,單介面應用程式,顧名思義就是所有動作都在一個頁面上完成,不會重新導向 index.html 以外的地方。其原理是 JavaScript 用 Ajax 動態從 Server 端拿資料,再即時 render 到 client 端上。
優點:
- 使用者體驗較佳。每次動態更新資料只會更新部分頁面,而不是導向完全不同的頁面。
- 前後端分工較明確。後端負責提供 API 給前端 render。
- 就算 JS 掛掉, HTML 檔案還是會顯示基本的畫面而非直接掛掉。
缺點
- 一個頁面要載入超多 .js 檔案,會跑比較慢。
- SEO 差。因為真正的內容要等 JS 渲染完,比較笨的爬蟲只看到 HTML 的話就是個空殼 → 可靠 SSR 解決。
- 前端變的超級複雜,還會有回傳順序的問題。要是沒寫好可能會出現「明明都點到第三頁了,卻顯示第一頁的畫面」這種狀況。
P1 你知道怎麼樣用 PHP 自己寫出 API
PHP 基礎語法:
// 建立一個空陣列
$json = array();
// 在陣列中增加一個新的物件
$array_push($json, array(
"id" => 13
));
// 轉換成 json 格式
$response = json_encode($json);
// 印出來看看
echo $respons;
// 結果 [{"id": 13}]
之後前端只要讀取 PHP echo 的 JSON 格式結果就好。
P1 你知道如何在前端與自己開的 API 串接
串接 API 的方法有很多種,以下示範用 jQuery 實作 Ajax 的方法:
$.ajax({
method: 'GET',
url: 'https://'
}).done(function(data) {
console.log(data)
}).fail(function(err)) {
console.log(err)
})
或是
$.ajax({
method: 'GET',
url: 'https://',
success: (data) => function,
error: (err) => functuon
})
P1 你知道在 server 與在 client render 的差別
server
- PHP拿出資料 → render 到 HTML 上 → 回傳 HTML 檔案給瀏覽器。
- 以上流程每進行一次就會刷新一次頁面。
client render
- PHP 拿出資料 → 變成特定格式(JSON) → 傳給 JavaScript → JavaScript render 到沒有資料的 HTML 上。
- 以上流程並不會更換頁面, PHP 只負責回傳 API 給前端,再由前端動態 render 到頁面上。
- 優缺點可參照上面 SPA 的條目。
也來借用 minw 助教提供的圖解:
P1 你知道 jQuery 是做什麼的
jQuery 是 JavaScript 的 library ,將常用的函式包在一起。早期瀏覽器和寫法都未被統一, jQuery 可以跨瀏覽器的特性是很大的優勢,也提供了更為簡潔的語法。
P1 你知道 jQuery 與 vanilla js 的差別
vanilla js 就是原生 JavaScript 。而 jQuery 則是以此為基礎建立的 library ,使用前要先引入檔案才能使用。前端發展至今大專案已經有更好維護的框架了,不過較小的專案使用 jQuery 自由度反而較高。
P1 你知道什麼是 Bootstrap、P2 你知道 Bootstrap 原理及如何應用
Bootstrap 是一個由 HTML、CSS 和 JavaScript 寫成的前端框架,核心的設計目標是達成RWD響應式與行動優先,也就是讓你的網站排版可以自動適應螢幕大小。
使用 Bootstrap 前要先引入檔案,其中設定好各種 CSS 樣式和 JavaStript 樣式,想使用時只要更改 HTML 中的 class 即可。
雖然 Bootstrap 提供各種 UI 對不善設計的工程師是一大福音,不過也因此出現了大量相似的網頁 XD
WEEK13
P1 你知道 webpack 的目的以及原理
Webpack 是一種 module bundler ,也就是可以將各種資源打包在一起,讓你可以在瀏覽器使用它。
之前使用 node.js 時,如果要將檔案外的模組(例如另一個檔案寫好一個功能後輸出)引入,可以使用 require
。但這個語法和瀏覽器不相容,相對的瀏覽器要使用 <script src='目標檔案'>
引入作為全域變數,但若一次引入不只一個檔案,可能會發生變數名稱衝突,此時就必須使用 jQuery 提供的 .conflic() 排除。
既然沒有支援就自己寫ㄅ,於是就出現各種非官方的模組化規範,直到最近出現 ES6 規範。不過 ES6 的規範支援度還是不好,例如必須開 Server 、 必須在引入時標註 type="module";
而且在想要引入其他人寫的套件時,必須將整份 node_modules
傳上去,或是在 import 輸入完整路徑,十分不好維護。
使用 Webpack 可以將所有檔案包成一個 main.js ,這樣瀏覽器只要引入就好了。更甚者它將模組的概念向外延伸至各種資源,像是 CSS 或圖片,再經過 loader 將資源打包成 .js 檔給瀏覽器使用。
P1 你熟悉如何使用 webpack 進行模組化開發
不太熟悉(喂)
以下簡單列一下使用自己的模組的基本流程好ㄌ:
- 在專案資料夾內安裝 webpack
npm init -y // 初始化 npm npm install webpack webpack-cli --save-dev // 安裝
設定
webpack.config.js
,最基本設定如下:const path = require('path'); module.exports = { mode: 'production', // 預設是production(壓縮代碼), development 指定為開發環境(未壓縮代碼) entry: './src/index.js', // 從哪裡引入模組 output: { filename: 'main.js', // 輸出之後放到哪裡 path: path.resolve(__dirname, 'dist'), }, };
- 設定
package.json
"scripts": { "build": "webpack", // 之後輸入 npm run build 時就會跑 webpack ㄌ "test": "echo \"Error: no test specified\" && exit 1" },
- 在檔案使用
require
和export
進行模組的輸入和輸出 npm run build
跑起來!
- 設定
另外在使用外部模組和 Loader 時,也是遵循安裝 → 更改設定檔和指令的方法。
P1 你知道如何使用 Promise、P2 你知道如何使用 fetch
資料來源:MDN - fetch 、 MDN - Promise
在 JavaScript 上想發非同步的 request 時,除了使用 XMLHttpRequest 以外,也可以使用 fetch 讓程式更簡潔。
最基本的語法是:
fetch('url')
之後如果要加 header 或其他設定可以用物件形式放在第二個參數中。另外,如果要 POST 的話,body
中的 content type 必須符合才行。
值得注意的是,因為 fecth 的回傳值不會 reject HTTP 的 error status ,因此之後還要額外偵測 status 才不會出現錯誤。另外, fetch 雖然可以接收跨站的 cookies ,卻不會主動傳送 cookies 。
fetch 出來的結果會以 Promise 形式出現,必須用 .then(cb)
才能取得其中內容。
Promise
是一個表示非同步運算的最終完成或失敗的物件。因此自己建立一個 Promise 必須輸入兩個函數:成功和失敗的值,而且通常只會有一個被觸發。以下是示意:
function init(resolve, reject) {
resolve(3);
reject(5);
}
const myPromise = new Promise(init)
myPromise.then((data) => {
console.log(data) // 如果成功就跑出 3
}).catch((err) => {
console.log(err) // 有錯誤的話就跑出 5
})
P2 你知道 gulp 的目的以及原理
glup 是一套 task manager
,將任務集中管理並設定執行流程。其中 task 的類型可以有很多種,也可以自訂功能。
P2 你知道 CSS Sprites 與 Data URI 的優缺點
參考資料:使用 DATA URI 將圖片以 Base64 編碼並內崁至網頁中,加速載入速度
CSS Sprites
是為了避免每次顯示一張圖就要發一次 HTTP request ,乾脆將所有小圖放在一張大圖上一次拿進來。顯示個別小圖的原理是先顯示大圖並設定成小圖的大小、設定成不重複,再位移到指定位置。這麼做的好處是全部只要載入一張圖,降低網路載入時間;但缺點是拼圖再選取的調整比較麻煩、不易維護,也不方便 SEO 讀取。
Data URI
是一種檔案格式,其資料全部都是經過 base64 編碼之後,以文字的方式來儲存的。優點是可以減少 HTTP 請求的數量,直接寫進 HTML 或 CSS 中,不需要透過外部的檔案儲存;不過維護時若要修改就要重新編碼,無法快取且易讀性很差,對 SEO 同樣不友善。
P2 你知道什麼是 uglify 與 minify
參考資料:wiki - 極簡化
minify
是在不影響功能的情況下,移除所有非功能性必要之原始碼字元,例如換行、空白、變數和函式名稱縮短之類,在不會影響運作的前提下將檔案縮小。
uglify
則是除了壓縮外,還會混淆程式碼,讓程式變得難以被人閱讀,可作為隱藏商業邏輯的手段。
P3 你熟悉如何使用 gulp 建構自動化工作流程
不知道(等等),以下紀錄跑 SASS 的方法,列一下在設定檔 gulpfile.js
要做的事:
const { src, dest } = require('gulp');
const sass = require('gulp-sass');
sass.compiler = require('node-sass');
function defaultTask() {
return src('src/*.scss') // 輸入這個檔案
.pipe(sass().on('error', sass.logError))
.pipe(dest('./css')) // 輸出成這個檔案
}
exports.default = defaultTask;
P3 你知道 CSS 優化的一些小技巧
前端的 CSS 優化主要分成三個方向:
- 資源大小
- minify:上面介紹過了。
- gzip:用重新編碼的方式壓縮,此時瀏覽器已經看不懂了,必須經過解碼才能解讀。主要由後端負責。
- 載入方式
- CSS Sprite :上面介紹過了,將小圖拼成大圖一起載入再分別呈現。
- Critical CSS:全部都要載入太慢了,先載入重要的部分。最簡單的作法是直接放至 .html 檔中。
- Cache:將傳過的東西放在 client 端。主要由後端負責。
執行方式
- CSS 選擇器:需要另外做判斷的 CSS Selector 較複雜,從 SASS 轉到 CSS 可能會變複雜,要注意。
- 屬性渲染:有些屬性可能會造成大規模重繪,例如用
top
定位不如用transform
,因為前者定位是用 layout 會牽扯較多東西。
## WEEK14
### P1 你知道虛擬空間、虛擬主機以及實體主機的差別
Dedicated Hosting
實體主機就是我們現在用的電腦的主機,如果用實體主機當伺服器的話,除了要像這週部屬時要裝好作業系統和架網路線外,維護起來也有點麻煩,尤其是一旦關機別人就進不來了 XD
Shared hosting
虛擬主機則是在遠端有台實體主機,然後切出不同的空間作為不同伺服器,但還是共用 CPU 、記憶體和硬碟,想像成宿舍有各自房間和公共空間那樣。雖然比實體主機方便維護,也較便宜,但缺乏獨立性,而且要是你鄰居習慣很差(像是流量大爆),你的伺服器就很容易不穩或當機。
Virtual Private Server
,也就是常聽到的 VPS也是大家共用一台主機,透過虛擬化技術把一台電腦硬體切成很多帳號,讓每個VPS帳號可以安裝自己的作業系統、軟體、自己管理。因為硬體成本還是大家一起均分,所以跟實體主機比起來,VPS的費用頓時也變低了~
P1 你知道什麼是網域(Domain)
Domain 全名是 Domain Name
,算是 IP 位置的代稱,方便人們閱讀。
P1 你知道如何設定網域(A、CNAME)
資料來源:PM筆記:HTTPS、A紀錄與CNAME
A 是 Address
。可以想像成 IP 位置是詳細地址,而域名則是建築物名。買好域名後 A 就是定位這棟建築物在哪裡,之後使用者輸入域名就會自動導向 A 的位置。
CNAME 全名是 Canonical Name
,是關連名稱與地點,其會指到一個網域名稱。用建築物來比喻可能是不同的餐廳(CNAME)都在同的大樓(網域)內,那不管我和司機說想去其中哪家餐廳都會自動被載到該大樓了。
P1 你知道如何用 SSH 遠端連線到自己的主機、P1 你知道如何部署應用程式
知道……吧(眼神飄忽)
P2 你知道什麼是 No SQL
參考資料:了解NoSQL不可不知的5項觀念 、 網站部署
無論是 SQL 或 NoSQL 指的都是拿來查詢資料庫的語言,而非資料庫系統。
關聯式資料庫 SQL
- 儲存格式為 table (像是表格那樣)
- table 之間互相關聯(例如 id 都一樣)
- 結構穩定,但相對彈性低,也不支援 JOIN 。
- Transaction 遵守 ACID 。
- 常見如 MySQL、PostgreSQL、Microsoft SQL Server、SQLite
非關聯式資料庫 NoSQL
- Not Only SQL
- 用不同型態儲存,因此資料可放的型態也更多元(例如陣列)
- 結構較不明顯,因此彈性更高,適合搜集數據。
- 相對的,查詢資料也比較慢。
- 使用 key-value 存資料,可以想像成 JSON。
- 具有水平擴充能力,只要增加新的伺服器節點,就可以不斷擴充資料庫系統的容量。
- Transaction 遵守 CAP 。
常見如 mongodb。
### P2 你知道什麼是 Transaction 與 lock
Transaction 指的是一組一次牽涉到多個 query 的操作,實際應用例如轉帳和購物。例如交易的時後小明給小美一百塊,這意味著小明少了一百,而小美多了一百這兩個操作。
此時只有兩個人還好,但使用者一多像是搶購票券之類的就會出問題,因為多筆資料同時進行更改時可能造成互相影響,比如說只有十張票卻有一百個人搶,發生 race condition ,最後發生超賣情形。
要避免這種狀況,只要在有人交易時先把門鎖上或放個標示說:「裡面有人ㄛ~」就可以避免了,這就是資料庫的 lock 。回到資料庫,為了維持 Transaction 的一致性(consistency)和隔離性(isolation),我們可以在資料被讀取或寫入時掛上一個 lock (像是公眾廁所燈有人使用時就會亮),其他 transaction 可以決定是否要等待或依然讀取。
P2 你知道資料庫的 ACID 是什麼
參考資料: 維基百科 - ACID
Transaction 是指由一系列資料庫操作組成的一個完整的邏輯過程,為了保證 Transaction 的正確性,要符合以下四個特性:
- 原子性 atomicity:要嘛全部失敗,要嘛全部成功。可以想像匯款的時後只有成功(錢過去了)或失敗(錢沒過去),不會出現這邊錢減少但那邊卻沒增加的情形。如果過程中發生錯誤,則會退回開始前的狀態,就像什麼都沒發生一樣。
- 一致性 consistency:維持資料的一致性。也就是錢的總數相同。
- 隔離性 isolation:多筆交易不會互相影響,比如說不能同時改同一個值,詳細作法可看前兩題。
持久性 durability:交易成功之後,寫入的資料不會不見,就算系統故障也不會消失。
### P3 你知道什麼是資料庫的 View 以及使用時機
View 是一張虛擬 table ,只能讀取不能改寫,好處是方便檢視不同 table 的特定欄位,在開放資料庫給他人時也方便隱藏比較機密的欄位,不過缺點是不易維護。
CREATE VIEW view_name [(column_list)] AS
SELECT column_name(s)
FROM table_name
WHERE condition;
P3 你知道什麼是 Stored procedure 以及如何使用
SQL 的 function 有分兩種,一種是內建函式例如 SUM()
,另一種則是 Stored procedure ,其設定完後可以直接取代 query 。
DELIMITER //
CREATE PROCEDURE functionName()
BEGIN
SQL query;
END //
DELIMITER ;
DELIMITER
是設定換行符號,先設定成 //
才不會和 Stored procedure 中的 query 撞到。
之後要使用 Stored procedure 就用 CALL functionName()
就可~
P3 你知道資料庫的 Trigger 以及使用時機
資料來源:維基百科 - trigger)
Trigger 的用於記錄資料庫的變動,並用 table 將變動記錄下來。
delimiter //
CREATE TRIGGER 名稱
BEFORE UPDATE FROM table名稱
FOR EACH ROW
BEGIN
要做什麼;
END //
delimiter;
跨題目資料來源
同學們的自我檢測: