Browse Source

fiot

yanyuan
zhizhi wu 4 years ago
parent
commit
0e8c93b45f
  1. 56
      signin/src/main/java/com/ccsens/signin/api/FiotExplorerController.java
  2. 31
      signin/src/main/java/com/ccsens/signin/bean/dto/FiotDto.java
  3. 18
      signin/src/main/java/com/ccsens/signin/bean/vo/FiotVo.java
  4. 2
      signin/src/main/java/com/ccsens/signin/service/UserService.java
  5. 5
      util/src/main/java/com/ccsens/util/WebConstant.java
  6. 2
      util/src/main/java/com/ccsens/util/wx/WxXcxUtil.java
  7. 74
      wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSignin.java
  8. 17
      wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSigninResponse.java
  9. 30
      wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/ResponseInfo.java
  10. 107
      wechatutil/src/main/java/com/ccsens/wechatutil/util/TC3Util.java
  11. 79
      wechatutil/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java

56
signin/src/main/java/com/ccsens/signin/api/FiotExplorerController.java

@ -0,0 +1,56 @@
package com.ccsens.signin.api;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.ccsens.signin.bean.dto.FiotDto;
import com.ccsens.signin.bean.dto.UserDto;
import com.ccsens.signin.bean.vo.FiotVo;
import com.ccsens.signin.bean.vo.UserVo;
import com.ccsens.signin.exception.UserLoginException;
import com.ccsens.util.JsonResponse;
import com.ccsens.util.WebConstant;
import com.ccsens.util.wx.WxXcxUtil;
import com.ccsens.wechatutil.wxfiotexplorer.FiotExplorerSigninUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @description:
* @author: whj
* @time: 2021/11/30 10:42
*/
@Slf4j
@Api(tags = "物联网", description = "")
@RestController
@RequestMapping("/fiot")
public class FiotExplorerController {
@ApiOperation(value = "物联网用户登录")
@ApiImplicitParams({
})
@RequestMapping(value = "/signin", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
public JsonResponse<FiotVo.Signin> userSignin(@ApiParam @Validated @RequestBody(required = true)FiotDto.Signin signin) throws Exception {
log.info("物联网用户登录:{}", signin);
String type = "FIOT";
WxXcxUtil.WechatUser wechatUser = WxXcxUtil.getUserInfo(signin.getCode(), type);
String token = FiotExplorerSigninUtil.getToken(wechatUser.openid, signin.getNickName(), signin.getAvatar(), WxXcxUtil.appId(type));
FiotVo.Signin vo = new FiotVo.Signin();
vo.setToken(token);
log.info("物联网用户登录结果:{}", vo);
return JsonResponse.newInstance().ok(vo);
}
}

31
signin/src/main/java/com/ccsens/signin/bean/dto/FiotDto.java

@ -0,0 +1,31 @@
package com.ccsens.signin.bean.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
/**
* @description:
* @author: whj
* @time: 2021/11/30 10:45
*/
public class FiotDto {
@Data
@ApiModel("登录-请求")
public static class Signin {
@NotEmpty
@ApiModelProperty("登录code")
private String code;
@NotEmpty
@ApiModelProperty("用户名")
private String nickName;
@NotEmpty
@ApiModelProperty("头像")
private String avatar;
}
}

18
signin/src/main/java/com/ccsens/signin/bean/vo/FiotVo.java

@ -0,0 +1,18 @@
package com.ccsens.signin.bean.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
/**
* @description:
* @author: whj
* @time: 2021/11/30 10:52
*/
public class FiotVo {
@Data
@ApiModel("物联网登录-返回")
public static class Signin{
private String token;
}
}

2
signin/src/main/java/com/ccsens/signin/service/UserService.java

@ -358,7 +358,7 @@ public class UserService implements IUserService {
if (sign == null) {
return null;
}
redisUtil.set(StrUtil.format(WebConstant.Wx.SESSION_KEY, sign.getUserId(), gameType), wechatUser.session_key);
redisUtil.set(StrUtil.format(WebConstant.Wx.SESSION_KEY, sign.getUserId(), gameType), wechatUser.session_key, WebConstant.Time.DAY);
return sign;
}

5
util/src/main/java/com/ccsens/util/WebConstant.java

@ -25,6 +25,10 @@ public class WebConstant {
/* 导入WBS ,规定标签长度 */
public static final Integer LABEL_LENGTH = 6;
public static class Time {
public static final long DAY = 24 * 3600 * 1000;
}
/**属性名*/
public static class Field{
public static final String CODE = "code";
@ -47,6 +51,7 @@ public class WebConstant {
}
public static final String SESSION_KEY = "{}_{}_session_key";
public static final String OPEN_KEY = "{}_{}_openid_key";
}

2
util/src/main/java/com/ccsens/util/wx/WxXcxUtil.java

@ -190,7 +190,7 @@ public class WxXcxUtil {
private static final String key = "";
private static String appId(String gameType){
public static String appId(String gameType){
switch (gameType){
case "SP":
return appid_sp;

74
wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSignin.java

@ -0,0 +1,74 @@
package com.ccsens.wechatutil.bean.po.wxfiotexplorer;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ccsens.wechatutil.util.TC3Util;
import lombok.Data;
import java.util.Calendar;
import java.util.Random;
import java.util.TimeZone;
import java.util.UUID;
/**
* @description:
* @author: whj
* @time: 2021/11/26 9:33
*/
@Data
public class FiotSignin {
/**
* 公共参数本接口取值AppGetTokenByWeiXin
*/
private String Action = "AppGetTokenByWeiXin";
/**
* 公共参数唯一请求 ID可自行生成推荐使用 uuid定位问题时需提供该次请求的 RequestId
*/
private String RequestId = UUID.randomUUID().toString();
/**
* 公共参数应用 AppKey 用于标识对应的小程序或 App
*/
private String AppKey = null;
/**
* 公共参数请求签名需用户自行生成用于校验请求的合法性
*/
private String Signature = null;
/**
* 公共参数请求的 UINX 时间戳秒级
*/
private long Timestamp = System.currentTimeMillis() / 1000;
/**
* 公共参数随机正整数 Timestamp 联合起来防止重放攻击
*/
private int Nonce = new Random().nextInt(10000);
/**
* 微信用户的 OpenID UnionID
*/
private String WxOpenID;
/**
* 昵称
*/
private String NickName;
/**
* 头像
*/
private String Avatar;
public FiotSignin() {
}
public FiotSignin(String openId, String nickName, String avatar, String appKey) throws Exception {
this();
this.WxOpenID = openId;
this.NickName = nickName;
this.Avatar = avatar;
this.AppKey = appKey;
this.Signature = TC3Util.generateSignature("iot", "iot.cloud.tencent.com", this.Timestamp, null);
}
}

17
wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSigninResponse.java

@ -0,0 +1,17 @@
package com.ccsens.wechatutil.bean.po.wxfiotexplorer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @description:
* @author: whj
* @time: 2021/11/30 10:25
*/
@Data
public class FiotSigninResponse {
@ApiModelProperty("截止时间,UINX 秒级时间戳")
private Long ExpireAt;
@ApiModelProperty("开发平台返回的 AccessToken,通过该 Token 进行登录后的接口请求")
private String Token;
}

30
wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/ResponseInfo.java

@ -0,0 +1,30 @@
package com.ccsens.wechatutil.bean.po.wxfiotexplorer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @description:
* @author: whj
* @time: 2021/11/30 10:17
*/
@Data
public class ResponseInfo<T> {
private Info<T> Response;
private String RequestId;
@Data
public static class Info<T>{
@ApiModelProperty("数据,异常时,data为空")
private T Data;
@ApiModelProperty("错误码,正确返回时,error为空")
private ErrorInfo Error;
}
@Data
public static class ErrorInfo{
private String Code;
private String Message;
}
}

107
wechatutil/src/main/java/com/ccsens/wechatutil/util/TC3Util.java

@ -0,0 +1,107 @@
package com.ccsens.wechatutil.util;
import cn.hutool.core.util.StrUtil;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.TreeMap;
/**
* @description:
* @author: whj
* @time: 2021/11/29 17:50
*/
public class TC3Util {
private final static Charset UTF8 = StandardCharsets.UTF_8;
private final static String SECRET_ID = "AKIDxhBRRAdplRpwnMfnfGaeRxDBsJTN0NTI";
private final static String SECRET_KEY = "Zrte9MPFo68tMZU8WcXDeqnVx95rYzA6";
private final static String CT_JSON = "application/json; charset=utf-8";
public static byte[] hmac256(byte[] key, String msg) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
return mac.doFinal(msg.getBytes(UTF8));
}
public static String sha256Hex(String s) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] d = md.digest(s.getBytes(UTF8));
return DatatypeConverter.printHexBinary(d).toLowerCase();
}
public static String generateSignature(String service, String host, long timestamp, String payload) throws Exception {
//String service = "cvm";
//String host = "cvm.tencentcloudapi.com";
// String region = "ap-guangzhou";
// String action = "DescribeInstances";
// String version = "2017-03-12";
String algorithm = "TC3-HMAC-SHA256";
//String timestamp = "1551113065";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 注意时区,否则容易出错
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));
// ************* 步骤 1:拼接规范请求串 *************
String httpRequestMethod = "POST";
String canonicalUri = "/";
String canonicalQueryString = "";
String canonicalHeaders = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n";
String signedHeaders = "content-type;host";
// String payload = "{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}";
String hashedRequestPayload = StrUtil.isEmpty(payload) ? "" : sha256Hex(payload);
String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"
+ canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;
System.out.println(canonicalRequest);
// ************* 步骤 2:拼接待签名字符串 *************
String credentialScope = date + "/" + service + "/" + "tc3_request";
String hashedCanonicalRequest = sha256Hex(canonicalRequest);
String stringToSign = algorithm + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
System.out.println(stringToSign);
// ************* 步骤 3:计算签名 *************
byte[] secretDate = hmac256(("TC3" + SECRET_KEY).getBytes(UTF8), date);
byte[] secretService = hmac256(secretDate, service);
byte[] secretSigning = hmac256(secretService, "tc3_request");
String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
System.out.println(signature);
// ************* 步骤 4:拼接 Authorization *************
String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", "
+ "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
TreeMap<String, String> headers = new TreeMap<String, String>();
headers.put("Authorization", authorization);
headers.put("Content-Type", CT_JSON);
headers.put("Host", host);
// headers.put("X-TC-Action", action);
// headers.put("X-TC-Timestamp", timestamp);
// headers.put("X-TC-Version", version);
// headers.put("X-TC-Region", region);
StringBuilder sb = new StringBuilder();
sb.append("curl -X POST https://").append(host)
.append(" -H \"Authorization: ").append(authorization).append("\"")
.append(" -H \"Content-Type: application/json; charset=utf-8\"")
.append(" -H \"Host: ").append(host).append("\"");
// .append(" -H \"X-TC-Action: ").append(action).append("\"")
// .append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"")
// .append(" -H \"X-TC-Version: ").append(version).append("\"")
// .append(" -H \"X-TC-Region: ").append(region).append("\"")
if (StrUtil.isNotEmpty(payload)) {
sb.append(" -d '").append(payload).append("'");
}
return sb.toString();
}
}

79
wechatutil/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java

@ -0,0 +1,79 @@
package com.ccsens.wechatutil.wxfiotexplorer;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ccsens.util.CodeError;
import com.ccsens.util.RedisUtil;
import com.ccsens.util.RestTemplateUtil;
import com.ccsens.util.exception.BaseException;
import com.ccsens.wechatutil.bean.po.wxfiotexplorer.FiotSignin;
import com.ccsens.wechatutil.bean.po.wxfiotexplorer.FiotSigninResponse;
import com.ccsens.wechatutil.bean.po.wxfiotexplorer.ResponseInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* @description:
* @author: whj
* @time: 2021/11/25 11:47
*/
@Slf4j
@Component
public class FiotExplorerSigninUtil {
private final static String SIGN_URL = "https://iot.cloud.tencent.com/api/exploreropen/appapi";
private final static String TOKEN_KEY = "FIOT_{}";
@Value("${fiot.appId:}")
private String appKey;
@Value("${fiot.secret:}")
private String appSecret;
@Resource
private RedisUtil redisUtil;
private static FiotExplorerSigninUtil util;
@PostConstruct
public void init(){
util = this;
util.redisUtil = this.redisUtil;
util.appKey = this.appKey;
util.appSecret = this.appSecret;
}
public static String getToken(String openId, String nickName, String avatar, String appKey) throws Exception {
log.info("物联网查询token:{},{},{}", openId, nickName, avatar);
String key = StrUtil.format(TOKEN_KEY, openId);
Object o = util.redisUtil.get(key);
log.info("{}缓存的token:{}", key, o);
if (o != null) {
return (String) o;
}
// 查询token
FiotSignin fiotSignin = new FiotSignin(openId, nickName, avatar, appKey);
log.info("登录:{}", fiotSignin);
String s = RestTemplateUtil.postBody(SIGN_URL, fiotSignin);
log.info("登录结果:{}", s);
if (StrUtil.isEmpty(s)) {
throw new BaseException(CodeError.THIRD_ERROR);
}
ResponseInfo<FiotSigninResponse> res = JSONObject.parseObject(s, ResponseInfo.class);
if (res.getResponse() == null) {
throw new BaseException(CodeError.THIRD_ERROR);
} else if (res.getResponse().getError() != null ) {
throw new BaseException(CodeError.THIRD_ERROR.getCode(), res.getResponse().getError().getMessage());
}
FiotSigninResponse data = res.getResponse().getData();
util.redisUtil.set(key, data.getToken(), data.getExpireAt() - System.currentTimeMillis()/1000);
return data.getToken();
}
}
Loading…
Cancel
Save