使用Google服务账号密钥认证Cloud Storage时遇文件名过长错误
问题:配置GOOGLE_APPLICATION_CREDENTIALS后提示“文件名过长”错误
环境变量配置(.env文件)
GOOGLE_APPLICATION_CREDENTIALS='{"type":"service_account","project_id":"xyz"...}'
对应代码
func GetSignedURL(w io.Writer) error { customEndpoint := "https://storage.googleapis.com/upload/storage/v1/b/bucket-name/o" ctx := context.Background() fmt.Println(len(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")))//<--2303 client, err := storage.NewClient(ctx, option.WithEndpoint(customEndpoint)) if err != nil { panic(err.Error())//<--file name too long } defer client.Close() fmt.Fprintf(w, "The request endpoint set for the client is: %v\n", customEndpoint) return nil }
使用的gcloud版本
$ gcloud --version Google Cloud SDK 412.0.0 alpha 2022.12.09 beta 2022.12.09 bq 2.0.83 bundled-python3-unix 3.9.12 core 2022.12.09 gcloud-crc32c 1.0.0 gsutil 5.17 minikube 1.28.0 skaffold 2.0.3
出现的错误
dialing: google: error getting credentials using GOOGLE_APPLICATION_CREDENTIALS environment variable: open {"type": "service_account","project_id":"xyz"...}: file name too long
原因及解决办法
核心原因
GOOGLE_APPLICATION_CREDENTIALS环境变量的设计用途是指向服务账号密钥文件的路径,而非直接存储密钥的JSON内容。Google Cloud SDK会将该变量的值当作文件名尝试打开,你把完整的JSON字符串填入后,SDK就会试图打开一个名称为该JSON内容的文件,自然会触发“文件名过长”的错误。
解决办法
方法一:使用密钥文件(推荐)
- 将从Google Cloud控制台获取的服务账号密钥保存为一个JSON文件,比如
service-account-key.json - 在.env文件中修改配置,将变量值设为该文件的绝对路径:
GOOGLE_APPLICATION_CREDENTIALS="/absolute/path/to/service-account-key.json"
方法二:直接在代码中使用JSON内容
如果必须直接通过环境变量传递JSON内容,不要使用GOOGLE_APPLICATION_CREDENTIALS,而是自定义一个环境变量(比如GOOGLE_SA_JSON),然后在代码中手动解析并创建凭证:
import ( "context" "os" "io" "fmt" "google.golang.org/api/option" "google.golang.org/api/credentials" "cloud.google.com/go/storage" ) func GetSignedURL(w io.Writer) error { customEndpoint := "https://storage.googleapis.com/upload/storage/v1/b/bucket-name/o" ctx := context.Background() // 从自定义环境变量获取JSON内容 saJSON := []byte(os.Getenv("GOOGLE_SA_JSON")) creds, err := credentials.NewCredentialsFromJSON(ctx, saJSON) if err != nil { panic(err.Error()) } client, err := storage.NewClient(ctx, option.WithCredentials(creds), option.WithEndpoint(customEndpoint)) if err != nil { panic(err.Error()) } defer client.Close() fmt.Fprintf(w, "The request endpoint set for the client is: %v\n", customEndpoint) return nil }
内容的提问来源于stack exchange,提问作者pigfox
相关产品推荐
相关产品推荐

