package httpapi import ( "errors" "net/http" "strings" "data-terminal-cloud/internal/identity" ) func BearerAuth(verifier identity.TokenVerifier, next http.Handler) http.Handler { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { rawToken, ok := bearerToken(request.Header.Get("Authorization")) if !ok { writer.Header().Set("WWW-Authenticate", "Bearer") WriteError(writer, request, http.StatusUnauthorized, "AUTHENTICATION_REQUIRED", "请先登录后再访问") return } principal, err := verifier.Verify(request.Context(), rawToken) if err != nil { writer.Header().Set("WWW-Authenticate", `Bearer error="invalid_token"`) WriteError(writer, request, http.StatusUnauthorized, "AUTHENTICATION_INVALID", "登录凭证无效或已经过期") return } next.ServeHTTP(writer, request.WithContext(identity.WithPrincipal(request.Context(), principal))) }) } func CurrentUserHandler(repository *identity.Repository) http.Handler { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { writer.Header().Set("Cache-Control", "no-store") principal, ok := identity.PrincipalFromContext(request.Context()) if !ok { WriteError(writer, request, http.StatusUnauthorized, "AUTHENTICATION_REQUIRED", "请先登录后再访问") return } currentUser, err := repository.CurrentUser(request.Context(), principal) switch { case errors.Is(err, identity.ErrAccountNotFound): WriteError(writer, request, http.StatusForbidden, "RESOURCE_ACCESS_DENIED", "当前账号无权访问该资源") case err != nil: WriteError(writer, request, http.StatusInternalServerError, "INTERNAL_ERROR", "服务暂时不可用") default: WriteJSON(writer, request, http.StatusOK, currentUser) } }) } func bearerToken(header string) (string, bool) { parts := strings.Fields(header) if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") || strings.TrimSpace(parts[1]) == "" { return "", false } return parts[1], true }