用户的个性化业务需求需要将产品下所有设备上报的数据传输至用户自有的服务器上进行处理,平台提供了 HTTP 转发服务,将设备上报数据实时 POST 到用户的 HTTP 服务器的能力。
客户需要一个HTTP的服务器去接收控制台传过来的设备信息。http服务器需要具备的功能如下:
如下示例代码是创建的Spring Boot项目,所有的业务逻辑均已在controller中展示
package com.example.datatrans.controller;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;
@RestController
public class DataTransCron {
static final String FILE_NAME = "device_report.txt";
@RequestMapping("deal_data")
public void dealDate(HttpServletRequest request, HttpServletResponse response) throws IOException {
//私有token,必须与页面写的token一致
String token = "此处填写【增加鉴权token】时,页面中填写的token";
List<String> list = new ArrayList<>();
String signature = "";
String echostr = "";
list.add(token);
if (request.getMethod().equalsIgnoreCase("GET")) {
//解析 header
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = request.getHeader(key);
System.out.printf("%s=%s\n",key,value);
if (key.equalsIgnoreCase("Echostr")){
echostr = value;
}
if (key.equalsIgnoreCase("Signature")){
signature = value;
}
if (key.equalsIgnoreCase("Timestamp")){
list.add(value);
}
if (key.equalsIgnoreCase("Nonce")){
list.add(value);
}
}
//校验签名
boolean success = checkSign(list, signature);
// 返回json字符串给客户端
response.setStatus(HttpStatus.OK.value());
response.setHeader("Content-Type", "application/json; charset=utf-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().print(success ? echostr : "验签失败");
//response.getWriter().print(echostr);
} else if (request.getMethod().equalsIgnoreCase("POST")) {
// 调用json包的解析,解析请求body
String body = getBodyFromReq(request);
System.out.println("request json : " + body);
//将body写入文件
writeInFile(FILE_NAME,body);
} else {
response.setStatus(HttpStatus.NOT_FOUND.value());
}
}
/**
* 校验签名
* @param list
* @param signature
* @return
*/
private boolean checkSign(List<String> list, String signature) {
//防止传入空的字符串骗过校验
if (list.size() == 0 || signature.length() == 0) {
return false;
}
String tmpStr = list.stream()
.sorted((a, b) -> a.compareTo(b))
.map(String::valueOf)
.collect(Collectors.joining(""));
System.out.println("tmpStr = " + tmpStr);
//加密生成hexValue
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] md5Bytes = sha.digest(tmpStr.getBytes(StandardCharsets.UTF_8));
//System.out.println("md5Bytes = " + md5Bytes);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
//System.out.println("hexValue = " + hexValue);
//System.out.println("是否相等 : " + hexValue.toString().equalsIgnoreCase(signature));
return hexValue.toString().equals(signature);
}
/**
* 从请求req中获取body对象
* @param request
* @return
*/
private String getBodyFromReq(HttpServletRequest request)
{
BufferedReader br = null;
StringBuilder sb = new StringBuilder("");
try
{
br = request.getReader();
String str;
while ((str = br.readLine()) != null)
{
sb.append(str);
}
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (null != br)
{
try
{
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return sb.toString();
}
/**
* 将content内容写到fileName文件中。如果文件不存在,创建文件,否则文件尾插入content
* @param fileName
* @param content
*/
private void writeInFile(String fileName, String content) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(fileName, true)));
out.write(content+"\r\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
用户收到的token验证的get请求示例如下:
GET / HTTP/1.1
Host: **.**.**.**:4443
User-Agent: Go-http-client/1.1
Content-Type: application/json
Echostr: UPWIAFASvDUFcTEE
Nonce: testrance
Signature: abb6c316a8134596d825c5a1295bfa6f7657664d
Timestamp: 1623149590
Accept-Encoding: gzip
用户收到返回的验证参数是:
HTTP/1.1 200 OK
Date: Tue, 08 Jun 2021 10:53:10 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8
UPWIAFASvDUFcTEE
用户收到控制台同步的信息示例如下:
{
"payload": {
"clientToken": "DEP****YAS4-38",
"method": "report",
"params": {
"brightness": 58,
"color": 2,
"name": "dev001",
"power_switch": 1
}
},
"seq": 1000000000,
"timestamp": 1579055948,
"topic": "$thing/up/property/DEP****YAS4/dev001",
"devicename": "dev001",
"productid": "DEP****YAS4"
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。