平台页面免密访问接入流程
<p><strong>日志:</strong> </p>
<table>
<thead>
<tr>
<th style="text-align: left;">版本号</th>
<th style="text-align: left;">撰写人</th>
<th style="text-align: left;">时间</th>
<th>修改内容</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">VA 1.0.0</td>
<td style="text-align: left;">lee</td>
<td style="text-align: left;">2021-05-06 10:09:27 星期四</td>
<td>创建</td>
</tr>
<tr>
<td style="text-align: left;">VA 1.1.0</td>
<td style="text-align: left;">lee</td>
<td style="text-align: left;">2021-05-06 15:05:07 星期四</td>
<td>redirectTo参数取消#符号前面的内容</td>
</tr>
</tbody>
</table>
<p><strong>简要描述:</strong> </p>
<ul>
<li>第三方平台通过界面跳转,免密访问物联网云平台的介绍</li>
</ul>
<p><strong>使用限制:</strong> </p>
<ul>
<li><strong>平台支持多账户,但第三方使用免密登录的账号,在平台暂不可同时用有多个账户</strong>,此举是为了权限和跳转路由的唯一性</li>
</ul>
<p><strong>接入流程:</strong> </p>
<ol>
<li>第三方平台向我司物联网云平台申请访问免密访问的私钥证书,请注意我司颁发的私钥为<code>pkcs8</code>格式</li>
<li>第三方平台通过约定的格式和加密方式,向我司物联网云平台发起请求</li>
<li>物联网云平台对请求参数和签名进行校验,不符合要求和规范的数据将会拒绝访问</li>
</ol>
<p><strong>请求URL示例:</strong> </p>
<ul>
<li><code>https://xxx.com?userTel=13110000000&amp;redirectTo=/console/index&amp;projectId=13317213&amp;signature=Cj5BGMLGNHNST2QyU5kCRS5py0CBP+ppH/k3kUNiuekbHkMhVG5DAigHJvLup1SSYyGnmHd+fNvZEFCLJWlR1gGc7ac5/iF06H6hM1Yq9mtsdR4N9NZ8WbBKiSnacvaoMykPBITT/JydSRhO9Ltynh0BYZZzQ5WrXuHsCGKta2bs3json9UVh3QDtUb6tHZdu4XtWUR1DU+88QL4xcE6e8lTzDCKENiMOJQ57VDgmW2G4mKiUuG83PlP0U/36R4pwsenHSP0P2Q6TtLSUnmK/KkdvK3PcTtQENzK3o1DQoupe6GMI6l9eeOKUs4OfzLXZY3UOH4NsL1HBuX2iC83ag==</code></li>
</ul>
<p><strong>注意:</strong> </p>
<ul>
<li><strong>以上数据只为示例</strong>,请以实际计算请求的为准</li>
</ul>
<p><strong>参数说明:</strong> </p>
<table>
<thead>
<tr>
<th style="text-align: left;">参数名</th>
<th style="text-align: left;">必选</th>
<th style="text-align: left;">类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">userTel</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">String</td>
<td>用户手机号</td>
</tr>
<tr>
<td style="text-align: left;">redirectTo</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">String</td>
<td>用户想要访问的界面路由。示例:<code>/console/index</code></td>
</tr>
<tr>
<td style="text-align: left;">projectId</td>
<td style="text-align: left;">否</td>
<td style="text-align: left;">String</td>
<td>用户想要访问对应界面须携带的资源参数,和<code>oemId</code>必传其一</td>
</tr>
<tr>
<td style="text-align: left;">oemId</td>
<td style="text-align: left;">否</td>
<td style="text-align: left;">String</td>
<td>用户想要访问对应界面须携带的资源参数,和<code>projectId</code>必传其一</td>
</tr>
<tr>
<td style="text-align: left;">signature</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">String</td>
<td>签名,为通过物联网平台颁布的私钥文件加密获得的签名值</td>
</tr>
</tbody>
</table>
<p><strong>signature的签名方式</strong></p>
<ul>
<li>
<p>signature 的签名源数据的组装方式为:<code>userTel{userTel值}redirectTo{redirectTo值}projectId{projectId值}</code>,当然<strong>如果请求URL传递的是oemId,此处也应由oemId组装</strong>,eg:</p>
<pre><code class="language-java">userTel13110000000redirectTo/console/indexprojectId13317213</code></pre>
<ol>
<li>用户需要对源数据(<strong>上述仅为示例,注意替换示例的userTel、projectId值</strong>)用私钥先进行<code>SHA256withRSA</code>签名</li>
<li>将步骤1得到的数据转为<code>Base64</code>编码格式,来作为<code>signature</code>的参数值进行传递</li>
</ol>
<p><strong>Java代码示例</strong> </p>
</li>
</ul>
<pre><code class="language-java"> /**
* 使用给定的密钥,对指定的buffer进行签名
* @param privateKey 给定的密钥。
* @param message 需要签名的消息
* @return 返回签名后的buffer
*/
public static byte[] sign(PrivateKey privateKey, byte[] message)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature sign = Signature.getInstance(&quot;SHA256withRSA&quot;);
sign.initSign(privateKey);
sign.update(message);
return sign.sign();
}
/**
* 对给定的字符串进行签名,并将签名后的内容转换成base64编码。
* @param privateKey
* @param message
* @return
*/
public static String signAndEncodeWithBase64(PrivateKey privateKey, String message)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
return Base64.getEncoder().encodeToString(sign(privateKey, message.getBytes()));
}
public static void main(String[] args) {
try {
ByteArrayOutputStream array = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int length;
FileInputStream inputStream = new FileInputStream(&quot;请替换为实际私钥文件的目录地址,eg:/home/user/Desktop/private_key.pem&quot;);
while ((length = inputStream.read(buffer)) != -1) {
array.write(buffer, 0, length);
}
String privateKey = array.toString(&quot;utf-8&quot;)
.replace(&quot;-----BEGIN PRIVATE KEY-----&quot;, &quot;&quot;)
.replace(&quot;-----END PRIVATE KEY-----&quot;, &quot;&quot;)
.replaceAll(&quot;\\s+&quot;, &quot;&quot;);
KeyFactory kf = KeyFactory.getInstance(&quot;RSA&quot;);
PrivateKey p = kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
String secret = signAndEncodeWithBase64(p, &quot;请替换为实际的签名源数据,eg:userTel13110000000redirectTo/console/indexprojectId13317213&quot;);
System.out.println(secret);
} catch (Exception e) {
e.printStackTrace();
}
}</code></pre>