Security headers & CORS
Brauzer — server va foydalanuvchi o‘rtasidagi vositachi. Server javob sarlavhalari orqali brauzerga ma’lumotni qanday qayta ishlash kerakligini aytadi: "bu javobni boshqa saytga ramka ichida ko‘rsatma", "faqat HTTPS orqali ulan", "Content-Typeni taxmin qilma". Bu sarlavhalar xavfsizlik sarlavhalari (security headers) deyiladi.
Ikkinchi mavzu — CORS. U brauzerga boshqa domendagi sahifaning sizning API’ngizdan ma’lumot o‘qishiga ruxsat bor-yo‘qligini aytadi.
1. Xavfsizlik sarlavhalari
Asosiy sarlavhalar
| Sarlavha | Qiymat (API uchun) | Nimadan himoya qiladi |
|---|---|---|
X-Content-Type-Options |
nosniff |
Brauzer Content-Typeni taxmin qilmaydi. JSON HTML sifatida ochilib ketmaydi |
Content-Security-Policy |
default-src 'none'; frame-ancestors 'none' |
XSS, begona resurslarni yuklash, ramkaga joylash |
X-Frame-Options |
DENY |
Clickjacking. Eski brauzerlar uchun frame-ancestorsning o‘rnini bosadi |
Referrer-Policy |
no-referrer |
URL’dagi maxfiy ma’lumot boshqa saytlarga Referer sarlavhasi orqali sizib chiqmaydi |
Strict-Transport-Security |
max-age=63072000; includeSubDomains |
HTTPS’dan HTTP’ga tushirish hujumlari. HTTP → HTTPS darsida ko‘rilgan |
Cache-Control |
no-store (shaxsiy ma’lumotlar uchun) |
Javob umumiy keshlarda va brauzer tarixida saqlanib qolmaydi |
Cross-Origin-Resource-Policy |
same-origin |
Boshqa saytlar javobni <img> yoki <script> orqali yuklay olmaydi |
Clickjacking — hujumchi sizning sahifangizni ko‘rinmas ramka (<iframe>) ichida ochadi va ustiga o‘z tugmalarini joylashtiradi. Foydalanuvchi "yutuqni olish" tugmasini bosyapman deb o‘ylaydi, aslida esa ramka ichidagi "akkauntni o‘chirish" tugmasini bosadi. frame-ancestors 'none' va X-Frame-Options: DENY sahifani ramkaga joylashni taqiqlaydi.
HTML sahifa qaytaradigan server uchun
Faqat JSON qaytaradigan API uchun eng qat’iy CSP yetarli. HTML sahifalar uchun esa CSP ancha murakkabroq bo‘ladi, chunki unda skriptlar, stillar va rasmlar manbalari ko‘rsatiladi:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
CSP’ni yoqishdan oldin uni Content-Security-Policy-Report-Only sarlavhasi bilan sinab ko‘ring. Bu rejimda brauzer hech narsani bloklamaydi, faqat qoidalar buzilgan holatlar haqida konsolda xabar beradi.
Middleware
func SecurityHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h := w.Header()
h.Set("X-Content-Type-Options", "nosniff")
h.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'")
h.Set("X-Frame-Options", "DENY")
h.Set("Referrer-Policy", "no-referrer")
h.Set("Cross-Origin-Resource-Policy", "same-origin")
if r.TLS != nil {
h.Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
}
next.ServeHTTP(w, r)
})
}
Middleware router’ni tashqaridan o‘rashi kerak. Shunda sarlavhalar 404 va boshqa xato javoblariga ham qo‘shiladi.
HSTS faqat HTTPS ulanishida qo‘shiladi. Proxy ortida esa buning o‘rniga ishonchli proxy’dan kelgan X-Forwarded-Proto tekshiriladi.
Keraksiz ma’lumotni yashirish
Go serveri Server yoki X-Powered-By kabi sarlavhalarni qo‘shmaydi. Bu yaxshi: hujumchi qaysi texnologiya ishlatilayotganini javobdan bila olmaydi. Proxy’lar, masalan nginx, bunday sarlavhani qo‘shishi mumkin. Ularni proxy sozlamalarida o‘chiring.
2. CORS
Same-origin siyosati
Brauzerda same-origin policy (bir manba siyosati) amal qiladi. Bir manbadagi sahifa boshqa manbadagi javobni JavaScript orqali o‘qiy olmaydi.
Manba (origin) uch qismdan iborat: sxema, host va port.
| URL | https://app.example.uz bilan bir manbami? |
|---|---|
https://app.example.uz/books |
✅ ha |
http://app.example.uz |
❌ sxema boshqa |
https://api.example.uz |
❌ host boshqa |
https://app.example.uz:8443 |
❌ port boshqa |
Bu siyosat foydalanuvchini himoya qiladi. Siz bank saytiga kirgan bo‘lsangiz, boshqa oynada ochilgan zararli sayt JavaScript orqali bank API’sidan hisobingiz qoldig‘ini o‘qiy olmaydi.
Lekin ko‘pincha frontend va API turli manbalarda joylashadi: https://app.example.uz va https://api.example.uz. Bu holatda API brauzerga "bu sahifaga mening javoblarimni o‘qishga ruxsat ber" deyishi kerak. CORS (Cross-Origin Resource Sharing) aynan shu mexanizm.
Info
CORS serverni himoya qilmaydi. U brauzerdagi same-origin cheklovini yumshatadigan mexanizm. curl, mobil ilova yoki boshqa server CORS qoidalariga umuman qaramaydi. Shuning uchun CORS autentifikatsiya va avtorizatsiyaning o‘rnini bosa olmaydi.
Oddiy so‘rovlar
GET yoki oddiy forma POST so‘rovi uchun brauzer so‘rovni yuboradi va unga Origin sarlavhasini qo‘shadi:
Server ruxsat bersa, javobga sarlavha qo‘shadi:
Sarlavha bo‘lmasa, brauzer javobni oladi, lekin uni JavaScript’ga bermaydi. Konsolda CORS xatosi chiqadi.
Preflight so‘rov
PUT, DELETE, Content-Type: application/json yoki Authorization sarlavhasi bor so‘rovlardan oldin brauzer ruxsat so‘raydi. Bu preflight so‘rov deb ataladi:
OPTIONS /books/42 HTTP/1.1
Origin: https://app.example.uz
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: authorization, content-type
Server ruxsat bersa:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.uz
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 600
Shundan keyingina brauzer asosiy DELETE so‘rovini yuboradi. Access-Control-Max-Age preflight natijasini 10 daqiqaga keshlaydi, shuning uchun har bir so‘rovdan oldin qayta ruxsat so‘ralmaydi.
Credentials: cookie va Authorization
Brauzer cookie’larni boshqa manbaga faqat frontend credentials: "include" bilan so‘rov yuborganda va server bunga aniq ruxsat berganda qo‘shadi:
Bu holatda muhim qoida bor: Access-Control-Allow-Origin: * ishlamaydi. Aniq manba ko‘rsatilishi shart.
Keng tarqalgan xatolar
// ❌ Har qanday manbaga cookie bilan ruxsat — CSRF va ma’lumot o‘g‘irlashga yo‘l
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Credentials", "true")
Bu kod so‘rov kelgan manbani tekshirmasdan qaytaradi. Natijada istalgan sayt foydalanuvchi nomidan API’dan ma’lumot o‘qiy oladi. Bu same-origin siyosatini butunlay o‘chirib qo‘yish bilan barobar.
// ❌ strings.Contains bilan tekshirish
if strings.Contains(origin, "example.uz") { ... }
// https://example.uz.evil.com ham o‘tib ketadi
To‘g‘ri yo‘l — aniq manbalar ro‘yxati bilan to‘liq solishtirish.
CORS middleware
type CORS struct {
allowed map[string]bool
}
func NewCORS(origins ...string) *CORS {
c := &CORS{allowed: make(map[string]bool)}
for _, o := range origins {
c.allowed[o] = true
}
return c
}
func (c *CORS) Handler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
w.Header().Add("Vary", "Origin")
if origin == "" || !c.allowed[origin] {
if r.Method == http.MethodOptions && origin != "" {
w.WriteHeader(http.StatusForbidden) // ruxsat etilmagan manbadan preflight
return
}
next.ServeHTTP(w, r) // CORS sarlavhalarisiz: brauzer javobni bloklaydi
return
}
h := w.Header()
h.Set("Access-Control-Allow-Origin", origin)
h.Set("Access-Control-Allow-Credentials", "true")
h.Set("Access-Control-Expose-Headers", "RateLimit-Remaining, X-Request-Id")
// Preflight so‘rov
if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" {
h.Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
h.Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
h.Set("Access-Control-Max-Age", "600")
w.WriteHeader(http.StatusNoContent)
return
}
next.ServeHTTP(w, r)
})
}
Muhim jihatlar:
Vary: Origin— javobOriginsarlavhasiga bog‘liq ekanini keshlarga bildiradi. Busiz CDN bitta manba uchun tayyorlangan javobni boshqa manbaga ham berib yuborishi mumkin.- Preflight router’ga yetkazilmaydi. Middleware
OPTIONSso‘roviga o‘zi javob beradi. Shuning uchun har bir marshrut uchunOPTIONShandler yozish shart emas. Bu gorilla/mux middleware darsida aytilgan muammoni ham hal qiladi. Access-Control-Expose-Headers— standart holatda JavaScript faqat bir nechta oddiy javob sarlavhalarini o‘qiy oladi.RateLimit-Remainingkabi maxsus sarlavhalarni ko‘rsatish uchun ular shu ro‘yxatga qo‘shiladi.- Middleware router’ni tashqaridan o‘raydi.
To‘liq misol
| main.go | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
Xavfsizlik sarlavhalari:
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'
X-Frame-Options: DENY
Referrer-Policy: no-referrer
GET https://app.example.uz → 200
Access-Control-Allow-Origin: https://app.example.uz
OPTIONS https://app.example.uz → 204
Access-Control-Allow-Origin: https://app.example.uz
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE
Access-Control-Max-Age: 600
OPTIONS https://evil.example → 403
GET https://app.example.uz.evil.com → 200
GET → 200
Natijalarni tahlil qilamiz:
- Ruxsat etilgan frontend
Access-Control-Allow-Originsarlavhasini oldi va preflight so‘rovi204bilan tasdiqlandi. evil.examplemanbasidan kelgan preflight403oldi. Brauzer asosiyDELETEso‘rovini umuman yubormaydi.app.example.uz.evil.commanbasi uchun javob qaytdi, lekin CORS sarlavhasiz. Brauzer bu javobni sahifaga bermaydi. To‘liq solishtirish soxta subdomen hiylasini to‘xtatdi.Originsarlavhasisiz so‘rov, ya’nicurlyoki mobil ilova, odatdagidek ishladi. Uni esa autentifikatsiya va avtorizatsiya himoya qiladi.
Tayyor kutubxona
CORS’ning ko‘plab nozik holatlarini hisobga oladigan tayyor kutubxona ham bor: github.com/rs/cors. U net/http bilan mos keladi va Gin hamda boshqa framework’lar uchun adapterlarga ega:
c := cors.New(cors.Options{
AllowedOrigins: []string{"https://app.example.uz"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowedHeaders: []string{"Authorization", "Content-Type"},
AllowCredentials: true,
MaxAge: 600,
})
handler := c.Handler(mux)
Xulosa
- Xavfsizlik sarlavhalari brauzerga javobni xavfsiz qayta ishlashni buyuradi. API uchun asosiylari:
nosniff, qat’iy CSP,frame-ancestors,Referrer-Policyva HSTS. - Sarlavhalar middleware orqali, router’ni tashqaridan o‘rab qo‘shiladi.
- Same-origin siyosati boshqa manbadagi javobni o‘qishni taqiqlaydi. CORS esa bu cheklovni ongli ravishda yumshatadi.
- CORS serverni himoya qilmaydi. U faqat brauzer uchun mo‘ljallangan qoida.
- Manbalar aniq ro‘yxat bilan to‘liq solishtiriladi.
Originni tekshirmasdan qaytarish vaContainsbilan tekshirish xavfli. - Cookie bilan ishlaganda
*ishlatib bo‘lmaydi.Vary: Originsarlavhasini unutmang.
Shu bilan kursning API bo‘limi yakunlandi. Unda HTTP server asoslaridan boshlab JSON, ma’lumotlar bazasi, autentifikatsiya, avtorizatsiya, routerlar, Gin, HTTPS va xavfsizlikkacha bo‘lgan mavzular ko‘rib chiqildi. Endi bu bilimlarni o‘z loyihangizda birlashtirib, to‘liq API yaratishingiz mumkin.