访问凭证管理 Basic Auth类型访问凭证 Basic Auth类型访问凭证创建参数说明如下: 参数名称 是否必填 参数说明 凭证名称 是 访问凭证名称同租户下唯一。 凭证名称规则:必须以字母开头,只能包含字母、数字、中划线和下划线,长度132个字符。 描述 否 访问凭证描述。 认证类型 是 认证类型支持3种,即:API Key、Basic Auth和JWT 用户名 是 用户名规则:必须以字母开头,只能包含字母、数字、下划线和中划线,长度132个字符。 密码 是 密码长度832个字符。 JWT类型访问凭证 JWT类型访问凭证创建参数说明如下: 参数名称 是否必填 参数说明 凭证名称 是 访问凭证名称同租户下唯一。 凭证名称规则:必须以字母开头,只能包含字母、数字、中划线和下划线,长度132个字符。 描述 否 访问凭证描述。 认证类型 是 认证类型支持3种,即:API Key、Basic Auth和JWT JWKS配置 是 JWKS目前只支持RS256算法 生成JWKS配置以及JWT,可以参考如下golang程序 plaintext func TestRsaJwksAndJWT(t testing.T) { // 定义要测试的 RSA 签名算法列表 algs : []string{ jwt.SigningMethodRS256.Name, } // 存储每种算法对应的私钥,用于后续 JWT 签名 privateKeys : make(map[string]rsa.PrivateKey) // 构建 JWKS keySet : jwk.NewSet() // 为每种算法生成独立的 RSA 密钥对,并添加到 JWKS for , alg : range algs { // 生成 RSA 密钥对 privateKey, err : rsa.GenerateKey(rand.Reader, 2048) if err ! nil { t.Fatalf("生成 RSA 私钥失败 (alg%s): %v", alg, err) } privateKeys[alg] privateKey // 从私钥获取公钥 publicKey : &privateKey.PublicKey // 构建 JWK jwkKey, err : jwk.FromRaw(publicKey) if err ! nil { t.Fatalf("构建 JWK 失败 (alg%s): %v", alg, err) } // 设置必要属性 if err : jwkKey.Set(jwk.KeyUsageKey, "sig"); err ! nil { t.Fatalf("设置 use 属性失败 (alg%s): %v", alg, err) } if err : jwkKey.Set(jwk.AlgorithmKey, alg); err ! nil { t.Fatalf("设置 alg 属性失败 (alg%s): %v", alg, err) } // 设置唯一的 kid(基于算法名称) kid : fmt.Sprintf("%skey", alg) if err : jwkKey.Set(jwk.KeyIDKey, kid); err ! nil { t.Fatalf("设置 kid 属性失败 (alg%s): %v", alg, err) } // 添加到 JWKS keySet.AddKey(jwkKey) // 打印 PEM 格式的私钥和公钥 fmt.Printf(" RSA 密钥对 (alg%s) n", alg) privateKeyPEM : pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey), }) fmt.Println("私钥 (PEM):") fmt.Println(string(privateKeyPEM)) publicKeyBytes, err : x509.MarshalPKIXPublicKey(publicKey) if err ! nil { t.Fatalf("序列化公钥失败 (alg%s): %v", alg, err) } publicKeyPEM : pem.EncodeToMemory(&pem.Block{ Type: "PUBLIC KEY", Bytes: publicKeyBytes, }) fmt.Println("公钥 (PEM):") fmt.Println(string(publicKeyPEM)) fmt.Println() } // 序列化 JWKS 为 JSON jwksJSON, err : json.MarshalIndent(keySet, "", " ") if err ! nil { t.Fatalf("序列化 JWKS 失败: %v", err) } fmt.Println(" JWKS (包含所有算法的公钥) ") fmt.Println(string(jwksJSON)) // 标准载荷(RegisteredClaims) now : time.Now() claims : &jwt.RegisteredClaims{ Issuer: "exampleissuer", Subject: "1234567890", Audience: []string{"exampleaudience"}, ExpiresAt: jwt.NewNumericDate(now.Add(time.Hour 24 30)), NotBefore: jwt.NewNumericDate(now), IssuedAt: jwt.NewNumericDate(now), ID: "uniquejwtid" + now.Format("20060102150405"), } // 遍历每种算法,生成并验证 JWT for , alg : range algs { t.Run(alg, func(t testing.T) { privateKey : privateKeys[alg] // 创建 JWT 令牌 token : jwt.NewWithClaims(jwt.GetSigningMethod(alg), claims) // 签名 signedToken, err : token.SignedString(privateKey) if err ! nil { t.Fatalf("签署 JWT 失败 (alg%s): %v", alg, err) } fmt.Printf(" JWT (alg%s) n%snn", alg, signedToken) // 验证 JWT:从 JWKS 中根据 kid 匹配公钥(kid 格式为 "算法key") parsedSet, err : jwk.Parse(jwksJSON) if err ! nil { t.Fatalf("解析 JWKS 失败: %v", err) } // 根据算法构造期望的 kid expectedKid : fmt.Sprintf("%skey", alg) // 通过 LookupKeyID 直接获取对应的 JWK targetKey, ok : parsedSet.LookupKeyID(expectedKid) if !ok { t.Fatalf("未找到 kid 为 %s 的公钥", expectedKid) } var pubKeyRaw interface{} if err : targetKey.Raw(&pubKeyRaw); err ! nil { t.Fatalf("获取原始公钥失败: %v", err) } // 解析并验证签名 parsedToken, err : jwt.ParseWithClaims(signedToken, &jwt.RegisteredClaims{}, func(token jwt.Token) (interface{}, error) { if token.Method.Alg() ! alg { return nil, jwt.ErrSignatureInvalid } return pubKeyRaw, nil }, jwt.WithLeeway(5time.Second)) if err ! nil { t.Fatalf("验证 JWT 失败: %v", err) } if !parsedToken.Valid { t.Fatal("JWT 无效") } // 验证载荷 gotClaims, ok : parsedToken.Claims.(jwt.RegisteredClaims) if !ok { t.Fatal("Claims 类型不正确") } if gotClaims.Subject ! claims.Subject { t.Errorf("subject 不匹配: got %v, want %v", gotClaims.Subject, claims.Subject) } if gotClaims.Issuer ! claims.Issuer { t.Errorf("issuer 不匹配: got %v, want %v", gotClaims.Issuer, claims.Issuer) } t.Logf("算法 %s 验证通过", alg) }) } }