Chuỗi bài: Go
go
73 dòng
· Cập nhật 2026-04-18
auth.go
Go/Baasid/internal/middleware/auth.go
// Package middleware hosts Echo middlewares shared across routes.
//
// The specification requires every goods CRUD request to carry a JWT in the
// Authorization header; we centralise verification here so handlers stay thin.
package middleware
import (
"net/http"
"strings"
"baasid/internal/auth"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
)
// Context keys used to pass authenticated identity from middleware to handlers.
// Using typed constants avoids string typos and collisions with other libs.
const (
// CtxUserID holds the caller's system_user._id as uuid.UUID.
CtxUserID = "baasid_ctx_user_id"
// CtxAccount holds the caller's login account string (for logging).
CtxAccount = "baasid_ctx_account"
)
// JWTAuth returns an Echo middleware that enforces a valid Bearer JWT.
//
// The spec labels missing/invalid credentials as HTTP 403「權限不足」for
// goods endpoints (login uses 401 for bad password). We follow that wording
// here so API responses match the requirement document exactly.
func JWTAuth(tokens *auth.TokenService) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
raw := c.Request().Header.Get(echo.HeaderAuthorization)
if strings.TrimSpace(raw) == "" {
// Echo.HTTPError.Message is rendered by router.customHTTPErrorHandler.
return echo.NewHTTPError(http.StatusForbidden, echo.Map{"message": "權限不足"})
}
// Accept either "Bearer <token>" (RFC 6750) or a raw token string,
// because the requirement document only says "JWT token".
token := strings.TrimSpace(raw)
if strings.HasPrefix(strings.ToLower(token), "bearer ") {
token = strings.TrimSpace(token[7:])
}
claims, err := tokens.ParseAccessToken(token)
if err != nil {
return echo.NewHTTPError(http.StatusForbidden, echo.Map{"message": "權限不足"})
}
uid, err := uuid.Parse(claims.UserID)
if err != nil {
return echo.NewHTTPError(http.StatusForbidden, echo.Map{"message": "權限不足"})
}
c.Set(CtxUserID, uid)
c.Set(CtxAccount, claims.Account)
return next(c)
}
}
}
// GetUserID reads the authenticated user's UUID from Echo context.
// Panics if middleware did not run — that is a programming error.
func GetUserID(c echo.Context) uuid.UUID {
v := c.Get(CtxUserID)
uid, ok := v.(uuid.UUID)
if !ok {
panic("middleware.GetUserID: CtxUserID not set — forgot JWT middleware?")
}
return uid
}
Bài viết liên quan
Go
go
Cập nhật 2026-04-18
main.go
main.go — go source code from the Go learning materials (Go/Baasid/cmd/hashpw/main.go).
Đọc bài viết →
Go
go
Cập nhật 2026-04-18
main.go
main.go — go source code from the Go learning materials (Go/Baasid/cmd/server/main.go).
Đọc bài viết →
Go
go
Cập nhật 2026-04-18
docs.go
docs.go — go source code from the Go learning materials (Go/Baasid/docs/docs.go).
Đọc bài viết →
Go
go
Cập nhật 2026-04-18
jwt.go
jwt.go — go source code from the Go learning materials (Go/Baasid/internal/auth/jwt.go).
Đọc bài viết →
Go
go
Cập nhật 2026-04-18
password.go
password.go — go source code from the Go learning materials (Go/Baasid/internal/auth/password.go).
Đọc bài viết →
Go
go
Cập nhật 2026-04-18
password_test.go
password_test.go — go source code from the Go learning materials (Go/Baasid/internal/auth/password_test.go).
Đọc bài viết →