Bảo mật trong Go - Bảo vệ Ứng dụng của Bạn! 🛡️
Chào mừng bạn đến với bài học về bảo mật trong Go! Trong bài học này, chúng ta sẽ tìm hiểu cách bảo vệ ứng dụng của bạn khỏi các mối đe dọa bảo mật.
Kiểm tra Đầu vào 🔍
1. Kiểm tra Chuỗi
func validateInput(input string) error {
if len(input) == 0 {
return errors.New("không được để trống")
}
if len(input) > 100 {
return errors.New("độ dài vượt quá giới hạn")
}
if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(input) {
return errors.New("chứa ký tự không hợp lệ")
}
return nil
}
💡 Giải thích:
- Kiểm tra độ dài chuỗi
- Kiểm tra ký tự hợp lệ
- Tránh dữ liệu độc hại
2. Ngăn chặn SQL Injection
// ✅ Đúng: Sử dụng tham số hóa
func getUser(db *sql.DB, id string) (*User, error) {
var user User
err := db.QueryRow("SELECT * FROM users WHERE id = $1", id).Scan(&user.ID, &user.Name)
if err != nil {
return nil, err
}
return &user, nil
}
// ❌ Sai: Nối chuỗi SQL
func getUser(db *sql.DB, id string) (*User, error) {
query := fmt.Sprintf("SELECT * FROM users WHERE id = %s", id)
// Dễ bị SQL injection
}
💡 Giải thích:
- Sử dụng prepared statements
- Tránh SQL injection
- Bảo vệ database
Xác thực 🔐
1. Xác thực JWT
type Claims struct {
UserID string `json:"user_id"`
jwt.StandardClaims
}
func generateToken(userID string) (string, error) {
claims := Claims{
UserID: userID,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
IssuedAt: time.Now().Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte("secret"))
}
💡 Giải thích:
- Tạo token JWT
- Thêm thời gian hết hạn
- Ký token an toàn
2. Mã hóa Mật khẩu
func hashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
func checkPassword(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
💡 Giải thích:
- Mã hóa mật khẩu an toàn
- Sử dụng bcrypt
- So sánh mật khẩu an toàn
Phân quyền 👥
1. Phân quyền theo Vai trò
type Role string
const (
RoleAdmin Role = "admin"
RoleUser Role = "user"
RoleGuest Role = "guest"
)
type User struct {
ID string
Role Role
}
func (u *User) CanAccess(resource string) bool {
switch u.Role {
case RoleAdmin:
return true
case RoleUser:
return resource != "admin"
case RoleGuest:
return resource == "public"
default:
return false
}
}
💡 Giải thích:
- Định nghĩa vai trò
- Kiểm tra quyền truy cập
- Phân quyền rõ ràng
2. Phân quyền theo Hành động
type Permission struct {
Resource string
Action string
}
type User struct {
ID string
Permissions []Permission
}
func (u *User) HasPermission(resource, action string) bool {
for _, p := range u.Permissions {
if p.Resource == resource && p.Action == action {
return true
}
}
return false
}
💡 Giải thích:
- Định nghĩa quyền chi tiết
- Kiểm tra quyền linh hoạt
- Dễ dàng mở rộng
Mã hóa Dữ liệu 🔒
1. Mã hóa AES
func encrypt(data []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}
return gcm.Seal(nonce, nonce, data, nil), nil
}
💡 Giải thích:
- Mã hóa dữ liệu an toàn
- Sử dụng AES-GCM
- Tạo nonce ngẫu nhiên
2. Mã hóa RSA
func generateKeyPair() (*rsa.PrivateKey, *rsa.PublicKey, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, err
}
return privateKey, &privateKey.PublicKey, nil
}
💡 Giải thích:
- Tạo cặp khóa RSA
- Độ dài khóa 2048 bit
- An toàn cho mã hóa
HTTPS 🌐
1. Cấu hình TLS
func setupTLS() (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
return nil, err
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
}, nil
}
💡 Giải thích:
- Cấu hình TLS an toàn
- Sử dụng TLS 1.2 trở lên
- Bảo vệ kết nối
2. Header Bảo mật HTTP
func securityHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-XSS-Protection", "1; mode=block")
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
next.ServeHTTP(w, r)
})
}
💡 Giải thích:
- Thêm header bảo mật
- Ngăn chặn XSS
- Bảo vệ khỏi clickjacking
Bảo mật File 📁
1. Kiểm tra File Upload
func validateFile(file multipart.File, header *multipart.FileHeader) error {
// Kiểm tra kích thước
if header.Size > 10<<20 { // 10MB
return errors.New("file quá lớn")
}
// Kiểm tra loại file
buff := make([]byte, 512)
_, err := file.Read(buff)
if err != nil {
return err
}
filetype := http.DetectContentType(buff)
if !strings.HasPrefix(filetype, "image/") {
return errors.New("loại file không hợp lệ")
}
return nil
}
💡 Giải thích:
- Kiểm tra kích thước file
- Kiểm tra loại file
- Ngăn chặn file độc hại
2. Lưu trữ File An toàn
func saveFile(file multipart.File, filename string) error {
// Tạo tên file an toàn
ext := filepath.Ext(filename)
name := uuid.New().String()
secureFilename := name + ext
// Lưu vào thư mục an toàn
dst, err := os.Create(filepath.Join("uploads", secureFilename))
if err != nil {
return err
}
defer dst.Close()
_, err = io.Copy(dst, file)
return err
}
💡 Giải thích:
- Tạo tên file ngẫu nhiên
- Lưu vào thư mục an toàn
- Tránh truy cập trực tiếp
Quản lý Phiên 🔑
1. Phiên An toàn
type Session struct {
ID string
UserID string
ExpiresAt time.Time
}
func createSession(userID string) (*Session, error) {
session := &Session{
ID: uuid.New().String(),
UserID: userID,
ExpiresAt: time.Now().Add(24 * time.Hour),
}
// Lưu vào cookie an toàn
cookie := &http.Cookie{
Name: "session",
Value: session.ID,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteStrictMode,
Expires: session.ExpiresAt,
}
return session, nil
}
💡 Giải thích:
- Tạo phiên an toàn
- Sử dụng cookie bảo mật
- Thêm thời gian hết hạn
Best Practices (Cách sử dụng tốt nhất) ✅
-
Kiểm tra đầu vào
// ✅ Đúng
if err := validateInput(input); err != nil {
return err
}
// ❌ Sai
// Không kiểm tra đầu vào -
Mã hóa mật khẩu
// ✅ Đúng
hashedPassword, err := hashPassword(password)
// ❌ Sai
// Lưu mật khẩu dạng text -
Sử dụng HTTPS
// ✅ Đúng
server := &http.Server{
TLSConfig: tlsConfig,
}
// ❌ Sai
// Không sử dụng HTTPS -
Quản lý phiên an toàn
// ✅ Đúng
cookie.Secure = true
cookie.HttpOnly = true
// ❌ Sai
// Cookie không an toàn
Tiếp theo 🎯
Trong các bài học tiếp theo, chúng ta sẽ:
- Tìm hiểu về testing
- Học cách tối ưu hiệu suất
- Khám phá các kỹ thuật nâng cao
- Thực hành với các dự án thực tế
💡 Lời khuyên: Bảo mật là một quá trình liên tục. Luôn cập nhật và kiểm tra bảo mật của ứng dụng thường xuyên để bảo vệ dữ liệu và người dùng!
func forceHTTPS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !r.URL.IsAbs() && r.Header.Get("X-Forwarded-Proto") != "https" {
url := "https://" + r.Host + r.RequestURI
http.Redirect(w, r, url, http.StatusMovedPermanently)
return
}
next.ServeHTTP(w, r)
})
}
Rate Limiting
Rate limiter implementation
type RateLimiter struct {
ips map[string]*rate.Limiter
mu *sync.RWMutex
r rate.Limit
b int
}
Rate limit middleware
func rateLimit(next http.Handler) http.Handler {
limiter := rate.NewLimiter(rate.Every(time.Second), 10)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "Too many requests", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
Logging
Secure logging
func logSecurityEvent(event SecurityEvent) {
log.Printf("[SECURITY] %s - IP: %s - User: %s - Action: %s",
time.Now().Format(time.RFC3339),
event.IP,
event.UserID,
event.Action,
)
}
Audit logging
func auditLog(action string, user User) {
log.Printf("[AUDIT] %s - User: %s - Action: %s - Timestamp: %s",
user.ID,
user.Email,
action,
time.Now().Format(time.RFC3339),
)
}
Best Practices
- Luôn validate và sanitize input
- Sử dụng prepared statements cho database queries
- Implement proper authentication và authorization
- Sử dụng HTTPS
- Implement rate limiting
- Xử lý file upload an toàn
- Implement proper logging
- Sử dụng secure headers
- Implement CSRF protection
- Regular security audits