API网关计算签名的方法

<p><span style="font-size:18px"><strong>拼接签名内容</strong></span></p> <p>API网关在计算签名前,需要按照以下格式生成签名原文:</p> <table border="0" cellpadding="0" cellspacing="0"> <tbody> <tr> <td style="background-color:#f7f8fa"> <p><span style="font-family:Consolas">String strToSign =<br /> &nbsp; &nbsp; HttpMethod + &quot;\n&quot; +<br /> &nbsp; &nbsp; URI + &quot;\n&quot; +<br /> &nbsp; &nbsp; Headers + &quot;\n&quot; +<br /> &nbsp; &nbsp; ContentDigest</span></p> </td> </tr> </tbody> </table> <p><strong>拼接格式说明</strong>:</p> <table border="1" cellpadding="0" cellspacing="0"> <tbody> <tr> <td style="background-color:#ededed; vertical-align:top; width:130px"> <p><strong>参数</strong></p> </td> <td style="background-color:#ededed; vertical-align:top; width:657px"> <p><strong>说明</strong></p> </td> </tr> <tr> <td style="vertical-align:top; width:130px"> <p>HttpMethod</p> </td> <td style="vertical-align:top; width:657px"> <p>API的调用方法,如GET、POST等。</p> </td> </tr> <tr> <td style="vertical-align:top; width:130px"> <p>URI</p> </td> <td style="vertical-align:top; width:657px"> <p>API的请求路径,格式为Path + Query:</p> <p><span style="font-family:Consolas">...</span></p> <p><span style="font-family:Consolas">String url =<br /> &nbsp; &nbsp; Path +<br /> &nbsp; &nbsp; &quot;?&quot; +<br /> &nbsp; &nbsp; Key1 + &quot;=&quot; + Value1 +<br /> &nbsp; &nbsp; &quot;&amp;&quot; + Key2 + &quot;=&quot; + Value2 +<br /> &nbsp; &nbsp; ...<br /> &nbsp; &nbsp; &quot;&amp;&quot; + KeyN + &quot;=&quot; + ValueN;</span></p> <p><span style="font-family:Consolas">...</span></p> <p>其中:</p> <p>&bull;&nbsp;&nbsp; Path:如果有非法字符,例如:中文等,需要根据 Percent-Encoding使用UTF-8字符集对其进行编码。</p> <p>&bull;&nbsp;&nbsp; Query:先对参数的名称即Key按照字典顺序排序,再按照如下方法进行拼接:</p> <p>&nbsp; &nbsp; &diams;&nbsp; &nbsp;如果参数为空,则 URL = Path,不需要添加<span style="font-family:Arial,Helvetica,sans-serif">&quot;?&quot;</span>。</p> <p>&nbsp; &nbsp; &diams;&nbsp; &nbsp;如果某个参数的Value为空,则只保留参数的Key参与计算签名,等号 = 不需要再加入签名。</p> <p>&nbsp; &nbsp; &diams;&nbsp; &nbsp;如果某个参数的Value存在多个,则多个Value需要按照<strong>字典顺序</strong>进行排序后参与签名计算。</p> <p>&nbsp; &nbsp; &nbsp; &nbsp; 例如:<span style="font-family:Consolas">String url = &quot;/some/path.html?key1=value1&amp;key2=value2&amp;key2=value3&amp;key3&quot;</span></p> <p><img src="https://obs-cn-shanghai.yun.pingan.com/pcp-portal/20193110093656-1c5f2d909a8d.png" style="height:26px; margin:0px; width:65px" />:Query中参数的Key和Value是未进行URLEncoding的原数据。</p> </td> </tr> <tr> <td style="vertical-align:top; width:130px"> <p>Headers</p> </td> <td style="vertical-align:top; width:657px"> <p>由参与签名计算的请求头中参数的Key、Value拼接而成的字符串。参与签名计算的请求头包括:PA-AG-Gateway-Timestamp以及PA-AG-Gateway-Signature-Headers。</p> <p><!--[if gte mso 9]><xml> <o:OLEObject Type="Embed" ProgID="PBrush" ShapeID="_x0000_i1026" DrawAspect="Content" ObjectID="_1633965004"> </o:OLEObject> </xml><![endif]--><img src="https://obs-cn-shanghai.yun.pingan.com/pcp-portal/20193010175017-19e172309ca6.png" style="height:26px; margin:0px; width:65px" />:请求头不区分大小写。</p> <p>Headers拼接方式:</p> <p>先对参与签名计算的请求头中参数的 Key 按照字典顺序排序,再按照如下方式进行拼接:</p> <p>&bull;&nbsp; &nbsp;如果请求头中某个参数的Value为空,则使用HeaderKey.toLowercase() + &quot;:&quot;参与签名,需要保留Key和英文冒号<span style="font-family:Consolas">&quot;:&quot;</span>,并且Key和Value左右两边不能有空白字符。</p> <p>&bull;&nbsp; &nbsp;如果请求头中某个参数的Value存在多个,多个Value需要按照字典顺序进行排序后参与签名计算。</p> <p>例如:</p> <p><span style="font-family:Consolas">...</span></p> <p><span style="font-family:Consolas">String headers =<br /> &nbsp; &nbsp; HeaderKey1.toLowercase() + &quot;:&quot; + HeaderValue1.toLowercase() + &quot;\n&quot;\+<br /> &nbsp; &nbsp; HeaderKey2.toLowercase() + &quot;:&quot; + HeaderValue2.toLowercase() + &quot;\n&quot;\+<br /> &nbsp; &nbsp; ...<br /> &nbsp; &nbsp; HeaderKeyN.toLowercase() + &quot;:&quot; + HeaderValueN.toLowercase() + &quot;\n&quot;</span></p> <p><span style="font-family:Consolas">...</span></p> </td> </tr> <tr> <td style="vertical-align:top; width:130px"> <p>ContentDigest</p> </td> <td style="vertical-align:top; width:657px"> <p>请求体的MD5值。</p> <p>存在请求体时,需要对请求体进行MD5转码。</p> <p>计算方式:</p> <p><span style="font-family:Consolas">String contentDigest = Base64.encodeBase64(MD5(requestBody.getbytes(&quot;UTF-8&quot;)));</span></p> </td> </tr> </tbody> </table> <p><span style="font-size:18px"><strong>生成签名结果</strong></span></p> <p>API网关生成签名原文后,通过签名密钥,按照设置的签名算法进行签名计算。</p> <p><strong>签名计算方法:</strong></p> <table border="0" cellpadding="0" cellspacing="0"> <tbody> <tr> <td style="background-color:#f7f8fa"> <p><span style="font-family:Consolas">Mac hmacSha256 = Mac.getInstance(&quot;HmacSHA256&quot;);<br /> byte[] keyBytes = secret.getBytes(&quot;UTF-8&quot;);<br /> hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, &quot;HmacSHA256&quot;));<br /> String sign = new String(Base64.encodeBase64(hmacSha256.doFinal(strToSign.getBytes(&quot;UTF-8&quot;)),&quot;UTF-8&quot;));</span></p> </td> </tr> </tbody> </table> <p>其中:</p> <p>&bull;&nbsp; &nbsp;secret:是绑定到API上的签名密钥的Secret。</p> <p>&bull;&nbsp;&nbsp; 签名算法:是创建API时选择的签名算法类型,目前支持HmacSHA1和HmacSHA256两种。</p> <p><span style="font-size:18px"><strong>传递签名结果</strong></span></p> <p>按照设置的签名算法进行签名计算后,API网关将签名结果放到PA-AG-Gateway-Signature字段中,并将在计算过程中所使用的签名密钥的Key放到PA-AG-Gateway-Sign-Key字段中。</p>
以上内容是否解决了您的问题?
请补全提交信息!
咨询·建议

电话咨询 - 7x24 小时

400-151-8800

邮件咨询

cloud@pingan.com

在线客服

7x24 小时,急速解答

工单支持

解决云产品相关技术问题