Implementando JWT no Gin Framework: Geração de Tokens e Autenticação com Middleware
O JWT (JSON Web Token) é uma tecnologia amplamente utilizada para autenticação em aplicações web. O projeto está disponível no GitHub:
https://github.com/dgrijalva/jwt-go/
Um token JWT é composto por três partes separadas por pontos: o cabeçalho (header), a carga útil (payload) e a assinatura. Por exemplo:
//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjYsImV4cCI6MTYzNzY2Nzk5OCwiaWF0IjoxNjM3MDYzMTk4LCJpc3MiOiJjaGVuZ3FpYW5nIiwic3ViIjoidXNlciB0b2tlbiJ9.nt8K7vxrAT4XXzh0RbtFveQCyt7J4r1XZnVgDNSVjkQ
Você pode decodificar cada parte usando base64. Por exemplo, para decodificar o cabeçalho:
echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 -D
Configuração JWT: utils/jwt.go
package utils
import (
"github.com/dgrijalva/jwt-go"
"meuProjeto/modelos"
"time"
)
// Chave secreta para assinar os tokens
var segredoJWT = []byte("minha-chave-secreta-2023")
type DadosToken struct {
IDUsuario uint
jwt.StandardClaims
}
// Gera um token após o login bem-sucedido
func GerarToken(usuario modelos.Usuario) (string, error) {
tempoExpiracao := time.Now().Add(7 * 24 * time.Hour) // Token válido por 7 dias
dados := &DadosToken{
IDUsuario: usuario.ID,
StandardClaims: jwt.StandardClaims{
ExpiresAt: tempoExpiracao.Unix(),
IssuedAt: time.Now().Unix(),
Issuer: "meu-sistema",
Subject: "autenticacao-usuario",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, dados)
tokenString, erro := token.SignedString(segredoJWT)
if erro != nil {
return "", erro
}
return tokenString, nil
}
// Analisa o token recebido do frontend
func ValidarToken(tokenString string) (*jwt.Token, *DadosToken, error) {
dados := &DadosToken{}
token, erro := jwt.ParseWithClaims(tokenString, dados, func(token *jwt.Token) (interface{}, error) {
return segredoJWT, nil
})
return token, dados, erro
}
Middleware para verificação de atuenticação
package middlewares
import (
"fmt"
"github.com/gin-gonic/gin"
"strings"
"meuProjeto/utils"
"meuProjeto/modelos"
)
// Middleware que verifica o token de autorização no cabeçalho da requisição
func Autenticacao() gin.HandlerFunc {
return func(c *gin.Context) {
// Obtém o token do cabeçalho Authorization
cabecalhoAutorizacao := c.GetHeader("Authorization")
fmt.Print("Token recebido:", cabecalhoAutorizacao)
// Verifica se o token existe e segue o formato "Bearer <token>"
if cabecalhoAutorizacao == "" || !strings.HasPrefix(cabecalhoAutorizacao, "Bearer ") {
c.JSON(401, gin.H{
"dados": gin.H{},
"meta": gin.H{
"mensagem": "Acesso não autorizado",
"codigo": 401,
},
})
c.Abort()
return
}
// Extrai o token removendo o prefixo "Bearer "
tokenString := cabecalhoAutorizacao[7:]
// Valida o token
token, dadosToken, erro := utils.ValidarToken(tokenString)
if erro != nil || !token.Valid {
c.JSON(401, gin.H{
"dados": gin.H{},
"meta": gin.H{
"mensagem": "Token inválido",
"codigo": 401,
},
})
c.Abort()
return
}
// Token válido, obtém o ID do usuário
idUsuario := dadosToken.IDUsuario
var usuario modelos.Usuario
// Busca o usuário no banco de dados
utils.DB.First(&usuario, idUsuario)
// Verifica se o usuário existe
if usuario.ID == 0 {
c.JSON(401, gin.H{
"dados": gin.H{},
"meta": gin.H{
"mensagem": "Usuário não encontrado",
"codigo": 401,
},
})
c.Abort()
return
}
// Armazena as informações do usuário no contexto da requisição
c.Set("usuario", usuario)
// Continua o processamento da requisição
c.Next()
}
}
Este middleware deve ser aplicaod às rotas que exigem autenticação. Ele verifica a presença e validade do token no cabeçalho Authorization, e se tudo estiver correto, permite o acesso à rota protegida.