前兩天的文章介紹了幾個跟安全性有關的 HTTP Header,但光認識這些 header 是不夠的,所以今天要來示範一下怎麼把這些安全性的 header 加到 API server 裡面去,讓你的服務可以真的變安全
首先來講講 Node.js 的部分,在 Express 裡面想要對所有的 response 都加上 header 非常簡單,只需要自己寫一個 middleware 再用 app.use()
套用上去就好了,譬如說我想加上前兩天講的四個 header,那就寫成這樣
const addSecurityHeaders = function(req, res, next) {
res.header('Content-Security-Policy', 'default-src larry.com');
res.header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
res.header('X-Content-Type-Options', 'nosniff');
res.header('X-Frame-Options', 'deny');
next();
}
// 所有的請求都會經過這個 middleware
app.use(addSecurityHeaders)
app.get('/api/user', getUserHandler)
app.post('/api/user', createUserHandler)
因為像這樣加上 header 的需求對 API server 來說非常常見,因此就有了 helmet 這個 middleware,你只要把他這頂安全帽戴上去,他就會幫你加上 CSP、HSTS、Expect-CT 等等各種你有聽過沒聽過的安全性 header。而且有了 helmet 之後只要定期去把他更到最新版,就不用再擔心幾年後又有新的 security header 出現
const helmet = require('helmet')
app.use(helmet())
app.get('/api/user', getUserHandler)
app.post('/api/user', createUserHandler)
而 Gin 的話作法跟 Express 非常像,也是先寫一個 middleware,然後再把這個 middleware 套用到所有的 API 上
func addSecurityHeaders(c *gin.Context) {
c.Writer.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
c.Writer.Header().Set("X-Content-Type-Options", "nosniff")
c.Writer.Header().Set("X-Frame-Options", "deny")
c.Next()
}
func main() {
router := gin.Default()
// 所有的請求都會經過這個 middleware
router.Use(addSecurityHeaders)
router.GET("/api/user", getUserHandler)
router.POST("/api/user", createUserHandler)
}
至於如果不想自己寫,有沒有跟 Node.js helmet 類似的第三方 library 在做這件事呢?
很可惜目前好像沒有,因為我自己也找了很久,但一直都沒有找到像 helmet 那麼好用的,所以如果有誰知道哪個 library 有這樣的功能,拜託一定要跟我說~
因為在 API Server 之前擋一台 Nginx 幾乎已經是 best practice 了,所以這邊也來示範要怎麼讓 Nginx 幫你加上那些 header
http {
upstream backend {
server 192.0.0.1:8000;
server 192.0.0.2:8000;
}
server {
listen 80;
# 只要進到這個 server 的請求,回覆時都會加上這些 header
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "deny";
location /api {
proxy_pass http://backend;
}
}
}
有了 Nginx 在前面幫忙加 header 後,後面的 API Server 就可以更專注在存粹的業務邏輯上,不用花時間在那邊加一堆雜七雜八的東西,處理請求的速度也會更快
今天講了怎麼把前兩天講到的 HTTP header 真的應用到實戰中,雖然看起來非常簡單,只是加幾行程式碼而已,但卻可以帶來很不錯的效果哦~
關於 security HTTP Header 的部分就到這邊結束,明天要開始講跟 cookie 安全性有關的部分了,如果對於這幾天的內容有問題的話歡迎在下方提問,沒問題那就明天見囉~