Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🐹
Intermediaire 25 min Go

Securiser une application Go

Pourquoi Securiser une application Go ?

La sécurité est un élément crucial dans tout développement logiciel moderne, y compris pour les applications Go. Dans un monde où la cybercriminalité continue à s'aggraver, il devient de plus en plus important de mettre en place des mesures de sécurité robustes pour protéger vos utilisateurs et votre application. Un cas d'usage concret est le traitement confidentiel des données personnelles : même une petite faille peut entraîner la perte de milliers de comptes.

Prerequis

Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :

  • Connaissances en Go : Vous devriez être familier avec les bases du langage Go.
  • Environnement de développement : Un environnement de développement Go configuré (Go installed, editor with Go support).
  • Gestionnaire de dépendances : go mod pour gérer les dépendances de votre projet.

Concepts fondamentaux

1. Authentification et Autorisation

L'authentification vérifie l'identité d'un utilisateur tandis que l'autorisation contrôle ce qu'il peut faire une fois authentifié.

// Exemple simplifié de l'utilisation de JWT pour l'authentification
package main

import (
	"net/http"
	"github.com/dgrijalva/jwt-go"
)

type Claims struct {
	UserID int `json:"user_id"`
	jwt.StandardClaims
}

func authenticateToken(w http.ResponseWriter, r *http.Request) (*Claims, error) {
	tokenString := r.Header.Get("Authorization")
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte("secret"), nil
	})
	if err != nil {
		return nil, err
	}
	claims, ok := token.Claims.(*Claims)
	if !ok || !token.Valid {
		return nil, err
	}
	return claims, nil
}

2. Hébergement sécurisé

Utilisez un hébergeur fiable et configurez vos serveurs pour minimiser les vulnérabilités.

// Exemple de configuration HTTP pour une application Go avec HTTPS
package main

import (
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, world!"))
	})

	srv := &http.Server{
		Addr: ":8443",
		TLSConfig: &tls.Config{
			Certificates: []tls.Certificate{cert},
		},
	}
	log.Fatal(srv.ListenAndServeTLS("", ""))
}

3. Protection contre les injections SQL

Utilisez des paramètres nommés pour éviter les injections SQL.

// Exemple d'utilisation de paramètres nommés avec sqlx
package main

import (
	"database/sql"
	"log"

	"github.com/jmoiron/sqlx"
)

func getUser(db *sqlx.DB, id int) (User, error) {
	var user User
	err := db.Get(&user, "SELECT id, name FROM users WHERE id=$1", id)
	return user, err
}

type User struct {
	ID   int    `db:"id"`
	Name string `db:"name"`
}

4. Sérialisation et deserialisation sécurisée

Utilisez des librairies de sérialisation fiables comme encoding/json avec des options pour éviter les attaques de déserialisation.

// Exemple d'utilisation de json.Unmarshal avec des options
package main

import (
	"encoding/json"
	"log"
)

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func unmarshalUser(data []byte) (*User, error) {
	var user User
	err := json.Unmarshal(data, &user)
	if err != nil {
		return nil, err
	}
	return &user, nil
}

Mise en pratique : projet fil rouge

Étape 1 : Configuration du projet

Créez un nouveau projet Go et initialisez-le avec go mod.

mkdir secure-go-app
cd secure-go-app
go mod init secure-go-app

Étape 2 : Création de la structure de base

Créez les fichiers suivants :

  • main.go
  • models/user.go
  • handlers/auth.go
  • middlewares/authMiddleware.go

Étape 3 : Implémentation de l'authentification JWT

// main.go
package main

import (
	"net/http"
)

func main() {
	http.HandleFunc("/login", authHandler)
	http.HandleFunc("/", protectedHandler, AuthMiddleware)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func authHandler(w http.ResponseWriter, r *http.Request) {
	// Implémentation de l'authentification
	w.Write([]byte("Login successful!"))
}

func protectedHandler(w http.ResponseWriter, r *http.Request) {
	// Implémentation de la gestion des requêtes protégées
	w.Write([]byte("Access granted to protected resource!"))
}

func AuthMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		claims, err := authenticateToken(r)
		if err != nil {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}
		ctx := context.WithValue(r.Context(), "user", claims)
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

func authenticateToken(r *http.Request) (*Claims, error) {
	tokenString := r.Header.Get("Authorization")
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte("secret"), nil
	})
	if err != nil {
		return nil, err
	}
	claims, ok := token.Claims.(*Claims)
	if !ok || !token.Valid {
		return nil, err
	}
	return claims, nil
}

type Claims struct {
	UserID int `json:"user_id"`
	jwt.StandardClaims
}
go
// models/user.go
package models

import (
	"time"
)

type User struct {
	ID        int       `json:"id"`
	Name      string    `json:"name"`
	CreatedAt time.Time `json:"created_at"`
}
go
// handlers/auth.go
package handlers

import (
	"net/http"

	"secure-go-app/models"
)

func registerHandler(w http.ResponseWriter, r *http.Request) {
	// Implémentation de l'inscription
	w.Write([]byte("Register successful!"))
}

func loginHandler(w http.ResponseWriter, r *http.Request) {
	// Implémentation de la connexion
	w.Write([]byte("Login successful!"))
}
go
// middlewares/authMiddleware.go
package middlewares

import (
	"net/http"

	"secure-go-app/models"
)

func AuthMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		claims, err := models.authenticateToken(r)
		if err != nil {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}
		ctx := context.WithValue(r.Context(), "user", claims)
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

Étape 4 : Exécution du projet

go run main.go handlers/auth.go models/user.go middlewares/authMiddleware.go

Erreurs frequentes et debugging

1. Erreur d'authentification JWT

Code incorrect :

tokenString := r.Header.Get("Authorization")
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
	return []byte("wrong-secret"), nil
})

Code correct :

tokenString := r.Header.Get("Authorization")
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
	return []byte("secret"), nil
})

2. Erreur de sérialisation

Code incorrect :

var user User
err := json.Unmarshal(data, &user)
if err != nil {
	return nil, err
}

Code correct :

var user User
err := json.Unmarshal(data, &user)
if err != nil {
	// Log de l'erreur pour débogage
	log.Printf("Error unmarshalling JSON: %v", err)
	return nil, err
}

3. Erreur d'injection SQL

Code incorrect :

var user User
err := db.Get(&user, "SELECT id, name FROM users WHERE id="+r.URL.Query().Get("id"))
if err != nil {
	return nil, err
}

Code correct :

var user User
err := db.Get(&user, "SELECT id, name FROM users WHERE id=$1", r.URL.Query().Get("id"))
if err != nil {
	return nil, err
}

Pour aller plus loin

1. Utilisation de frameworks web sécurisés comme Gin ou Echo

2. Sécurité des sessions et cookies

  • Utilisation de cookies HttpOnly et Secure
  • Gestion des sessions avec des clés secrètes robustes

3. Logging et monitoring

  • Utilisation de loggers spécialisés comme Zap ou Sugared Logger
  • Configurer des alertes et des métriques pour surveiller les activités de sécurité

Défi pratique

Créez un gestionnaire de mots de passe avec des fonctionnalités suivantes :

  • Inscription d'utilisateurs avec mot de passe haché
  • Connexion sécurisée avec JWT
  • Changement de mot de passe
  • Protection contre l'injection SQL

Besoin d'aide sur Go ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Comment sécuriser les connexions HTTP dans ma application Go?
Pour sécuriser les connexions HTTP, utilisez le package 'net/http' avec un serveur HTTPS en utilisant des certificats SSL/TLS valides. Vous pouvez également utiliser un middleware pour vérifier l'authentification et l'autorisation des requêtes.
Quelles sont les meilleures pratiques pour le stockage des mots de passe dans ma application Go?
Utilisez le package 'golang.org/x/crypto/bcrypt' pour hacher les mots de passe avant de les stocker. Assurez-vous que vos mots de passe ne sont jamais stockés en clair et mettez en place une politique stricte pour la gestion des mots de passe.
Comment prévenir les injections SQL dans ma application Go?
Utilisez les placeholders ('?') lors de l'exécution de requêtes SQL pour éviter les injections SQL. Assurez-vous que toutes les entrées utilisateur sont correctement échappées avant d'être utilisées dans des requêtes SQL directes.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.