消费者认证鉴权

云原生API网关支持全局认证、路由配置认证和消费者鉴权,以实现对API访问的控制、安全性和策略管理,确保只有授权的请求才能访问服务。本文介绍如何配置消费者鉴权,对API的调用者进行身份验证,确保请求是由授权的API消费者发起。

背景信息

相比全局认证鉴权适用于统一登录认证等ToC场景,路由、API开启消费者认证,适用于授权API给合作伙伴等ToB场景。

对比项

全局认证鉴权

路由认证+消费者鉴权

适用场景

统一登录认证等ToC场景。

授权API给合作伙伴等ToB场景。

核心差异

开启认证的同时也开启鉴权。

开启认证后,需要额外做鉴权配置。

配置入口

实例 > 安全管理 > 全局认证鉴权

  1. API管理 > HTTP-API详情 > 路由管理 > 策略配置 > 认证

  2. API管理 > REST-API详情 > 挂载策略 > 消费者认证

  3. 消费者 > 消费者详情 > 消费者鉴权

认证方式配置(以JWT认证为例)

  1. 创建配置时填写全局的JWKS配置。

  2. 填写issuesub字段作为识别JWT是否合法的依据。

  1. 创建消费者配置时填写该消费者对应的JWKS配置。

  2. 填写消费者标识用于识别JWT是否为对应的消费者。默认为payload中的uid字段,可以自定义。

鉴权方式配置

创建配置时填写黑名单或白名单的域名路径(Path)列表。

  • 黑名单模式:名单中的域名路径(Path)需要进行认证,其余无需认证可直接访问。

  • 白名单模式:名单中的域名和路径(Path)不需要认证即可访问,其余需要进行认证。

  1. 在路由、API的策略配置中为路由、API开启认证

  2. 消费者鉴权中授权开启了认证的路由或者API,完成授权。

注意事项

当用户在消费者认证中开启认证后,认证策略会即时生效,如果此时路由或者API已发布,但是又未给路由或者API配置消费者和授权规则,则默认会拒绝所有访问请求。

配置消费者认证鉴权

重要
  • 对于未发布的API或路由,建议您在授权完成后,再发布路由或者API,此时认证鉴权策略会自动生效。

  • 对于已发布的API或路由,建议您先在策略配置中将消费者认证置为关闭状态,等授权完成后,再开启策略,使其生效。

步骤一:开启路由或者API认证

登录云原生API网关控制台。在左侧导航栏,选择API,并在顶部菜单栏选择地域。在API列表页面,单击目标API名称:

HTTP API路由认证

  1. 进入路由列表页面,单击目标路由,选择策略配置页签。

  2. 单击消费者认证,配置认证方式和开启状态。

image

参数

描述

开启

开启后,认证鉴权生效。

认证方式

当前路由认证消费者时使用的认证方式。目前支持JWT、AK/SK、API key的认证方式。

REST API认证

  1. 进入详情页后,单击全部接口(API级策略&插件配置),在右侧的策略插件树中进行配置,在入站处理单击启用策略/插件

    image

  2. 在启用策略/插件控制面板,选择添加策略页签,单击消费者认证卡片。

    image

  3. 配置认证方式和开启状态。

    参数

    描述

    开启

    开启后,认证鉴权生效。

    重要

    对于已发布的API或路由,建议您先挂载消费者认证,待授权完成后,再启用该策略。

    认证方式

    当前路由认证消费者时使用的认证方式。目前支持JWT、AK/SK、API key的认证方式。

说明

WebSocket API暂不支持路由认证。

步骤二:创建消费者

  1. 登录云原生API网关控制台

  2. 在左侧导航栏,选择消费者

  3. 消费者页面左上角,单击创建消费者

  4. 创建消费者页面,填写消费者名称,选择如下认证方式并单击创建

    JWT认证

    image

    配置参数说明如下:

    配置项

    描述

    消费者名称

    自定义消费者的名称。

    描述

    对消费者进行描述。

    认证方式

    当前消费者支持的认证方式,目前主要支持JWT、AK/SK、API Key三种认证方式。

    密钥类型

    • 对称密钥:生成一份默认的JWKS配置(每个消费者不同),包含加密或者解密Token时使用的密钥。

    • 非对称密钥:需要您自己填写完整的JWKS配置,使用私钥加密Token。网关根据JWKS中配置的公钥进行解密。

    JWKS

    设置JWKS配置,JWKS规范说明请参考JSON Web Key (JWK)

    JWT Token配置

    设置JWT Token配置信息。

    • 类型:Token参数类型,默认Header。

    • Key:Token参数名称。

    • 前缀:Token参数名的前缀。设置需要校验的Token参数信息,默认是以Bearer为前缀放在Authorization Header中,例如Authorization: Bearer token

    • 是否透传:选中Token参数透传,表示透传此Token参数到后端服务。

    JWT Payload 内消费者标识

    指定从JWT Payload中的Key以及对应Value来识别为当前消费者。默认提供一对标识,Key为uid,Value为随机字符串,可以自行修改。

    JWT Token中的Payload配置示例如下所示:

    {
      "uid": "11215ac069234abcb8944232b79ae711"
    }

    AK/SK(HMAC)认证

    image

    配置参数说明如下:

    配置项

    描述

    消费者名称

    自定义消费者的名称。

    消费者说明

    对消费者进行描述。

    认证方式

    当前消费者支持的认证方式,目前主要支持JWT、AK/SK、API Key三种认证方式。

    生成方式

    • 系统生成:系统为您自动生成AK、SK配置。

    • 自定义:自定义AK、SK配置。

    API Key认证

    image

    配置参数说明如下:

    配置项

    描述

    消费者名称

    自定义消费者的名称。

    消费者说明

    对消费者进行描述。

    认证方式

    当前消费者支持的认证方式,目前主要支持JWT、AK/SK、API Key三种认证方式。

    生成方式

    • 系统生成:系统为您自动生成API Key凭证。

    • 自定义:自定义API Key凭证及凭证来源。

    凭证来源

    凭证来源用于网关从请求的提取参数的位置和名称,支持如下:

    • Authorization: Bearer <token>

    • 自定义 HTTP Header

    • 自定义Query String

步骤三:授权给消费者

  1. 在左侧导航栏,单击消费者,进入消费者列表页面。

  2. 单击目标消费者进入详情页,选择消费者授权页签,单击授权

  3. 在授权面板中,配置相关参数,单击确定

    添加API授权

    image

    参数

    描述

    API类型

    选择REST API

    生效环境名称/ID

    要授权的环境。

    授权范围

    支持对API或者接口进行访问控制。

    选择API(授权范围为API)

    授权的API。

    生效API(授权范围为接口)

    要授权接口所属的API。

    选择接口(授权范围为接口)

    要授权的接口。

    添加路由授权

    image

    参数

    描述

    API类型

    选择HTTP API

    授权范围

    对路由进行授权。

    生效API

    要授权接口所属的API。

    选择路由

    要授权的路由。

步骤四:认证策略生效

  • 对于未发布的API或路由,授权完成后,发布路由或者API,认证鉴权策略将自动生效,具体操作,请参见发布API发布路由规则

  • 对于已发布的API或路由,授权完成后,重新开启消费者授权认证策略,使其生效。

使用消费者认证鉴权

JWT认证

JWT认证流程概览:

image

  1. 客户端向API网关发起认证请求,请求中一般会携带终端用户的用户名和密码。

  2. 网关将请求直接转发给后端服务。

  3. 后端服务读取请求中的验证信息(比如用户名、密码)进行验证,验证通过后使用私钥生成标准的Token,返回给网关。

  4. 网关将携带Token的应答返回给客户端,客户端需要将这个Token缓存到本地。

  5. 客户端向API网关发送业务请求,请求中携带Token。

  6. 网关使用用户设定的公钥对请求中的Token进行验证,验证通过后,将请求透传给后端服务。

  7. 后端服务进行业务处理后应答。

  8. 网关将业务应答返回给客户端。

下文主要介绍生成Token、客户端向网关发送请求、网关使用设定的公钥进行Token验证的过程。

认证服务生成Token

下文将通过Java示例来说明Token的生成方式,其他语言您也可使用相关的工具生成密钥对。

  1. 新建Maven项目并注入依赖。

    首先,新建一个Maven项目,注入如下依赖项:

    <dependency>
        <groupId>org.bitbucket.b_c</groupId>
        <artifactId>jose4j</artifactId>
        <version>0.7.0</version>
    </dependency>
  2. 选择Token生成方式。

    您可以选择使用默认对称密钥示例生成Token和非对称密钥示例生成Token两种方式来生成Token。根据您的需求进行选择:

    使用默认对称密钥示例生成Token

    代码示例:

    package org.example;
    
    import java.io.UnsupportedEncodingException;
    import java.security.PrivateKey;
    
    import org.jose4j.base64url.Base64;
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jwk.OctJwkGenerator;
    import org.jose4j.jwk.OctetSequenceJsonWebKey;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.keys.HmacKey;
    import org.jose4j.lang.JoseException;
    import sun.lwawt.macosx.CSystemTray;
    
    public class Main {
        public static void main(String[] args) throws JoseException, UnsupportedEncodingException {
            //使用本文上述示例
            String privateKeyJson = "{\n"
                    + "    \"k\": \"VoBG-oyqVoyCr9G56ozmq8n_rlDDyYMQOd_DO4GOkEY\",\n"
                    + "    \"kty\": \"oct\",\n"
                    + "    \"alg\": \"HS256\",\n"
                    + "}";
            JwtClaims claims = new JwtClaims();
            claims.setGeneratedJwtId();
            claims.setIssuedAtToNow();
            //设置过期时间,并且小于7天
            NumericDate date = NumericDate.now();
            date.addSeconds(120*60);
            claims.setExpirationTime(date);
            claims.setNotBeforeMinutesInThePast(1);
            //添加自定义参数,所有值请都使用String类型
            //设置消费者标识
            claims.setClaim("uid", "11215ac069234abcb8944232b79ae711");
            JsonWebSignature jws = new JsonWebSignature();
            //设置加密算法
            jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
            jws.setKey(new HmacKey(Base64.decode(JsonUtil.parseJson(privateKeyJson).get("k").toString())));
            jws.setPayload(claims.toJson());
            String jwtResult = jws.getCompactSerialization();
            System.out.println("Generate Json Web token , result is \n " + jwtResult);
        }
    }

    代码相关设置说明:

    • privateKeyJson:即在创建消费者时使用的JWKS,可以在创建消费者时记录下自己使用的JWKS,也可以在创建消费者后,在消费者基础配置页获取JWKS。

      image

    • 设置消费者标识。即claims.setClaim("uid", "11215ac069234abcb8944232b79ae711"),该消费者标识为创建消费者时控制台默认生成,也可以根据自身逻辑进行修改。您也可以在创建消费者后,在消费者基础配置页获取消费者标识。

      image

    • 设置加密算法。即jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256),该加密算法要和JWKS保持一致。

      说明

      目前支持的加密算法有ES256、ES384、ES512、RS256、RS384、RS512、PS256、PS384、PS512、HS256、HS384、HS512和EdDSA。

      使用对称加密的时,需要对"k"进行解码。

      image

      jws.setKey(new HmacKey(Base64.decode(JsonUtil.parseJson(privateKeyJson).get("k").toString())));
    • 设置过期时间。过期时间需要小于7天,超出过期时间后,请重新生成Token,以保证Token的安全性。

      ...
          NumericDate date = NumericDate.now();
          date.addSeconds(120*60);
          claims.setExpirationTime(date);
          claims.setNotBeforeMinutesInThePast(1);
      ...
    • 根据自身业务需要,可以在JWKS的PAYLOAD中添加自定义参数。

    使用非对称密钥示例生成Token

    代码示例:

    package org.example;
    
    import java.io.UnsupportedEncodingException;
    import java.security.PrivateKey;
    
    import org.jose4j.base64url.Base64;
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jwk.OctJwkGenerator;
    import org.jose4j.jwk.OctetSequenceJsonWebKey;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.keys.HmacKey;
    import org.jose4j.lang.JoseException;
    import sun.lwawt.macosx.CSystemTray;
    
    public class Main {
        public static void main(String[] args) throws JoseException, UnsupportedEncodingException {
            //使用本文上述示例
            String privateKeyJson = "{\n"
                    + "    \"k\": \"VoBG-oyqVoyCr9G56ozmq8n_rlDDyYMQOd_DO4GOkEY\",\n"
                    + "    \"kty\": \"oct\",\n"
                    + "    \"alg\": \"HS256\",\n"
                    + "}";
            JwtClaims claims = new JwtClaims();
            claims.setGeneratedJwtId();
            claims.setIssuedAtToNow();
            //设置过期时间,并且小于7天
            NumericDate date = NumericDate.now();
            date.addSeconds(120*60);
            claims.setExpirationTime(date);
            claims.setNotBeforeMinutesInThePast(1);
            //添加自定义参数,所有值请都使用String类型
            //设置消费者标识
            claims.setClaim("uid", "11215ac069234abcb8944232b79ae711");
            JsonWebSignature jws = new JsonWebSignature();
            //设置加密算法
            jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
            jws.setKey(new HmacKey(Base64.decode(JsonUtil.parseJson(privateKeyJson).get("k").toString())));
            jws.setPayload(claims.toJson());
            String jwtResult = jws.getCompactSerialization();
            System.out.println("Generate Json Web token , result is \n " + jwtResult);
        }
    }

    代码相关设置说明:

    • 设置privateKeyJson、消费者标识、过期时间,同对称加密算法。

      设置加密算法,即jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256)。该加密算法和JWKS保持一致。

      image

      对于非对称加密算法,要用其私钥进行加密。

      ...
          jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
          PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyJson)).getPrivateKey();
          jws.setKey(privateKey);
      ...
    • 根据自身业务需要,可以在JWKS的PAYLOAD中添加自定义参数。

客户端向网关发送业务请求

目前云原生API网关支持Header的模式传递Token,客户可以自定义请求Header的名字和Token的前缀,请求验证时必须与消费者认证方式配对的key和前缀保持一致。

image

  • 请求不携带提供JWT,返回401。

    curl  http://xxx.hello.com/test
  • 请求携带错误JWT,返回401。

    curl  http://xxx.hello.com/test -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ1'
  • 请求携带JWT,但JWT代表的消费者无权访问API或者路由时,返回403。

    # consumer1没有授权给下列路径指定路由或者api
    
    curl  'http://xxx.example.com/test' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

服务端验证Token请求

服务端验证Token主要分为以下三步:

  1. 服务端收到用户请求时,先检查是否携带Token,未携带Token的请求,直接拒绝,返回401。

  2. 携带Token的请求,使用用户jwks中配置的私钥验证Token是否合法且有效,不合法或者失效,直接拒绝,返回401。

  3. 如果Token合法且有效后,再校验其代表的消费者是否授权给正在访问的API或者路由。

常见错误码说明

HTTP 状态码

出错信息

原因说明

401

Jwt missing

请求头未提供JWT

401

Jwt expired

JWT已经过期

401

Jwt verification fails

JWT payload校验失败,如iss不匹配

403

Access Denied

无权限访问当前路由

AK/SK(HMAC)认证

客户端生成签名

客户端生成签名流程概览:

  1. 提取签名串:从原始请求中提取关键数据,得到一个用来签名的字符串。

  2. 加密签名:使用加密算法和配置的SK对关键数据签名串进行加密处理,得到签名。

  3. 添加签名:将签名所相关的所有头加入到原始HTTP请求中,得到最终HTTP请求。

步骤一:提取签名串

客户端需要从Http请求中提取出关键数据,组合成一个签名串,生成的签名串格式如下:

HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters

以上7个字段构成整个签名串,字段之间使用\n间隔,如果Headers字段为空,则不需要加\n,其他字段如果为空都需要保留\n。签名对大小写敏感。下面介绍每个字段的提取规则:

  • HTTPMethod:HTTP的方法,全部大写,例如POST。

  • Accept:请求中的Accept头的值,可为空。建议显式设置Accept Header。当Accept为空时,部分Http客户端会给Accept设置默认值为 */*,导致签名校验失败。

  • Content-MD5:请求中的Content-MD5头的值,可为空。只有在请求存在Body且Body为非Form形式时才计算Content-MD5头,下面是Java的Content-MD5值的参考计算方式:

    String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
  • Content-Type:请求中的Content-Type头的值,可为空。

  • Date:请求中的Date头的值,当未开启date_offset配置时,可为空,否则将用于时间偏移校验。

  • Headers:用户可以选取指定的Header参与签名,关于Header的签名串拼接方式有以下规则:

    • 参与签名计算的Header的Key按照字典排序后使用如下方式拼接。

      HeaderKey1 + ":" + HeaderValue1 + "\n"\+
      HeaderKey2 + ":" + HeaderValue2 + "\n"\+
      ...
      HeaderKeyN + ":" + HeaderValueN + "\n"
    • 某个Header的Value为空,则使用HeaderKey+":"+"\n"参与签名,需要保留Key和英文冒号。

    • 所有参与签名的Header的Key的集合使用英文逗号分割放到Key为X-Ca-Signature-Headers的Header中。

    • 以下Header不参与Header签名计算:X-Ca-Signature、X-Ca-Signature-Headers、Accept、Content-MD5、Content-Type、Date。

  • PathAndParameters: 这个字段包含Path,Query和Form中的所有参数,具体组织形式如下:

    Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
    重要
    • Query和Form参数对的Key按照字典排序后使用上面的方式拼接。

    • Query和Form参数为空时,则直接使用Path,不需要添加

    • 参数的Value为空时只保留Key参与签名,等号不需要再加入签名。

    • Query和Form存在数组参数时(key相同,value不同的参数) ,取第一个Value参与签名计算。

步骤二:加密签名

客户端从HTTP请求中提取出关键数据组装成签名串后,需要对签名串进行加密及编码处理,形成最终的签名。具体的加密形式如下,其中 stringToSign 为提取出来的签名串,secret 为AK/SK认证身份配置中的SK,sign 为最终生成的签名:

Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] secretBytes = secret.getBytes("UTF-8");
hmacSha256.init(new SecretKeySpec(secretBytes, 0, secretBytes.length, "HmacSHA256"));
byte[] result = hmacSha256.doFinal(stringToSign.getBytes("UTF-8"));
String sign = Base64.encodeBase64String(result);

总结:将 stringToSign 使用UTF-8解码后得到Byte数组,然后使用加密算法对Byte数组进行加密,使用Base64算法进行编码,形成最终的签名。

步骤三:添加签名

客户端需要将以下四个Header放在HTTP请求中传输给API网关,进行签名校验:

  • x-ca-key:取值为AK/SK认证身份配置中的AK。

  • x-ca-signature-method:签名算法,取值HmacSHA256或者HmacSHA1,可选,默认值为HmacSHA256。

  • x-ca-signature-headers:所有签名头的Key的集合,使用英文逗号分隔,可选。

  • x-ca-signature:签名,必选。

服务端签名验证

服务器验证客户端签名概览:

image

  1. 提取签名串:从接收到的请求中提取关键数据,得到一个用来签名的字符串。

  2. 提取AK:从接收到的请求中读取AK ,通过AK 查询到对应的SK。

  3. 计算签名:使用加密算法和SK对关键数据签名串进行加密处理,得到签名。

  4. 签名验证:从接收到的请求中读取客户端签名,对比服务器端签名和客户端签名的一致性。

异常处理

网关签名校验失败时,会将服务端的签名串(StringToSign)放到HTTP Response的Header中返回到客户端,Key为:X-Ca-Error-Message,用户只需要将本地计算的签名串(StringToSign)与服务端返回的签名串进行对比即可找到问题。如果服务端与客户端的StringToSign一致,请检查用于签名计算的AK/SK认证身份中的SK是否正确。因为HTTP Header中无法表示换行,因此StringToSign中的换行符都被替换成#,如下所示:

X-Ca-Error-Message:  Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`

相关错误码

HTTP 状态码

出错信息

原因说明

401

Invalid Key

请求头未提供x-ca-key,或者x-ca-key无效。

401

Empty Signature

请求头未提供x-ca-signature签名串。

400

Invalid Signature

请求头x-ca-signature签名串,与服务端计算得到签名不一致。

400

Invalid Content-MD5

请求头content-md5不正确。

400

Invalid Date

根据请求头date计算时间偏移超过配置的 date_offset。

413

Request Body Too Large

请求Body超过限制大小:32 MB。

413

Payload Too Large

请求Body超过全局配置DownstreamConnectionBufferLimits。

403

Unauthorized Consumer

请求的调用方无访问权限。

API Key认证

按照设置的凭证来源方式来验证请求,API与路由请求类似,下面以路由为例:

API Key的凭证来源主要有三类:

  1. 默认凭证来源:Authorization: <Bearer> Token。

  2. 自定义Header,填写Header参数名。

  3. 自定义Query参数,填写query参数名。

默认凭证来源

假设以下请求会匹配到这条路由 abc ,将API Key设置在http特定请求头(Authorization)中,并为API Key追加前缀Bearer留意Bearer与API Key中间留有空格。

curl  http://xxx.test.com/test -H 'x-api-key: Bearer 2bda943c-ba2b-11ec-ba07-00163e1250b5'

将API Key设置在http请求头中

curl  http://xxx.test.com/test -H 'x-api-key: Bearer 2bda943c-ba2b-11ec-ba07-00163e1250b5'

自定义header来源

假设以下请求会匹配到这条路由 abc ,API Key 设置在 http 请求头中。

  • 如果路由未开启消费者认证鉴权策略,则拒绝访问,提示401。

    curl  http://xxx.test.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5
  • 如果路由已开启消费者认证鉴权策略,但未授权,则提示403。

    curl  http://xxx.test.com/test -H 'x-api-key: 2bda943c-ba2b-11ec-ba07-00163e1250b5'

自定义Query参数

假设以下请求会匹配到这条路由 abc ,将 API Key 设置在 url 参数中

  • 如果路由未开启消费者认证鉴权策略,则拒绝访问,提示401。

    curl  http://xxx.test.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5
  • 如果路由已开启消费者认证鉴权策略,但未授权,则提示403。

    curl  http://xxx.test.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5

相关错误码

HTTP 状态码

出错信息

原因说明

401

Request denied by Key Auth check. Muti API key found in request.

请求提供多个 API Key。

401

Request denied by Key Auth check. No API key found in request.

请求未提供 API Key。

401

Request denied by Key Auth check. Invalid API key.

不允许当前 API Key 访问。

403

Request denied by Key Auth check. Unauthorized consumer.

请求的调用方无访问权限。