iT邦幫忙

2021 iThome 鐵人賽

DAY 13
2

前言

前兩天的文章介紹了幾個跟安全性有關的 HTTP Header,但光認識這些 header 是不夠的,所以今天要來示範一下怎麼把這些安全性的 header 加到 API server 裡面去,讓你的服務可以真的變安全

Node.js

首先來講講 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)

Go

而 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 有這樣的功能,拜託一定要跟我說~

Nginx

因為在 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 安全性有關的部分了,如果對於這幾天的內容有問題的話歡迎在下方提問,沒問題那就明天見囉~


上一篇
Day12-記得要戴安全帽(二)
下一篇
Day14-守護餅乾大作戰(一)
系列文
從以卵擊石到堅若磐石之 Web API 安全性全攻略30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言