Spec Backend Com Golang E Gin • Trilha Progressiva em 4 Níveis


🎯 Nível 1: Fundamentos

Problema 10.1 — Hashing Seguro com golang.org/x/crypto/bcrypt

Contexto: Hashing Seguro com golang.org/x/crypto/bcrypt no contexto de Autenticação Stateless com JWT e Hashing de Senhas.

Requisitos de Execução:

  1. Criar funções para gerar hash Bcrypt de senha com custo 12 e comparar senha plana com hash.

Resultado Esperado

Senha plana validada com hash Bcrypt.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_10_1_SeuNome
  2. Envie na tarefa: Atividade Cap 10 - Autenticação Stateless com JWT e Hashing de Senhas
🔑 Gabarito de Código & Solução Comentada
// security/bcrypt.go
package security

import "golang.org/x/crypto/bcrypt"

func HashSenha(senha string) (string, error) {
	bytes, err := bcrypt.GenerateFromPassword([]byte(senha), 12)
	return string(bytes), err
}

func ChecarSenha(senha, hash string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(senha))
	return err == nil
}

🔍 Nível 2: Prática

Problema 10.2 — Geração e Assinatura de Token JWT com golang-jwt/jwt/v5

Contexto: Geração e Assinatura de Token JWT com golang-jwt/jwt/v5 no contexto de Autenticação Stateless com JWT e Hashing de Senhas.

Requisitos de Execução:

  1. Criar token JWT assinado com claims customizados contendo user_id, email e tempo de expiração.

Resultado Esperado

Token JWT assinado com chave secreta HMAC-SHA256.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_10_2_SeuNome
  2. Envie na tarefa: Atividade Cap 10 - Autenticação Stateless com JWT e Hashing de Senhas
🔑 Gabarito de Código & Solução Comentada
// security/jwt.go
package security

import (
	"time"
	"github.com/golang-jwt/jwt/v5"
)

var SecretKey = []byte("super_segredo_gin_api_2026")

type CustomClaims struct {
	UserID uint   `json:"user_id"`
	Email  string `json:"email"`
	jwt.RegisteredClaims
}

func GerarJWT(userID uint, email string) (string, error) {
	claims := CustomClaims{
		UserID: userID,
		Email:  email,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(SecretKey)
}

⚡ Nível 3: Integração

Problema 10.3 — Middleware Gin de Validação de Token Bearer

Contexto: Middleware Gin de Validação de Token Bearer no contexto de Autenticação Stateless com JWT e Hashing de Senhas.

Requisitos de Execução:

  1. Extrair cabeçalho Authorization: Bearer <token>, validar assinatura e injetar claims no contexto Gin.

Resultado Esperado

Token validado no middleware -> Claims disponibilizados no contexto.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_10_3_SeuNome
  2. Envie na tarefa: Atividade Cap 10 - Autenticação Stateless com JWT e Hashing de Senhas
🔑 Gabarito de Código & Solução Comentada
// middlewares/auth.go
package middlewares

import (
	"net/http"
	"strings"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"espec_backend_go_gin/security"
)

func ExigirJWT() gin.HandlerFunc {
	return func(c *gin.Context) {
		authHeader := c.GetHeader("Authorization")
		if !strings.HasPrefix(authHeader, "Bearer ") {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"erro": "Token não fornecido"})
			return
		}
		tokenStr := strings.TrimPrefix(authHeader, "Bearer ")
		claims := &security.CustomClaims{}
		token, err := jwt.ParseWithClaims(tokenStr, claims, func(t *jwt.Token) (interface{}, error) {
			return security.SecretKey, nil
		})
		if err != nil || !token.Valid {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"erro": "Token inválido ou expirado"})
			return
		}
		c.Set("user_id", claims.UserID)
		c.Next()
	}
}

🏆 Nível 4: Desafio Corporativo

Problema 10.4 — Rotação de Chaves e Revogação com Blacklist no Redis

Contexto: Rotação de Chaves e Revogação com Blacklist no Redis no contexto de Autenticação Stateless com JWT e Hashing de Senhas.

Requisitos de Execução:

  1. Verificar se o JTI (JWT ID) do token está presente na lista de tokens revogados no Redis antes de autorizar.

Resultado Esperado

Token revogado bloqueado com 401 Unauthorized.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_10_4_SeuNome
  2. Envie na tarefa: Atividade Cap 10 - Autenticação Stateless com JWT e Hashing de Senhas
🔑 Gabarito de Código & Solução Comentada
// security/blacklist.go
package security

var BlacklistMock = make(map[string]bool)

func IsTokenRevogado(jti string) bool {
	return BlacklistMock[jti]
}

func RevogarToken(jti string) {
	BlacklistMock[jti] = true
}