Commit e3b3c416 by 袁伟铭

1.0.0

parent 8586f14f
......@@ -4,6 +4,7 @@ import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zq.api.constant.ApiCodeEnum;
import com.zq.api.form.ApiForm;
import com.zq.api.form.ApiResp;
......@@ -43,6 +44,12 @@ public class ApiController {
long start = System.currentTimeMillis();
ApiForm form = ServletUtil.toBean(request, ApiForm.class, true);
try {
JSONObject jsonObject = JSON.parseObject(form.getBizContent());
form.setBizContentJson(jsonObject);
} catch (Exception e) {
return ApiUtils.getParamError(form);
}
// 不处理Request Method:OPTIONS的请求
if (request.getMethod().equals("OPTIONS")) {
......
......@@ -38,9 +38,14 @@ public class ApiForm {
private String version; // 接口版本
private String apiNo; // 接口码
private String bizContent; // 请求业务参数
private JSONObject bizContentJson; // 请求业务的json对象
private ApiTokenVo apiTokenVo;
public JSONObject getBizContentJson() {
public JSONObject getContentJson() {
if (bizContentJson != null) {
return bizContentJson;
}
JSONObject object = JSON.parseObject(bizContent);
if (object == null) {
return new JSONObject();
......@@ -97,7 +102,7 @@ public class ApiForm {
* @return
*/
public String get(String key) {
return getBizContentJson().getString(key);
return getContentJson().getString(key);
}
/**
......@@ -107,7 +112,7 @@ public class ApiForm {
* @return
*/
public Boolean getBoolean(String key) {
return getBizContentJson().getBoolean(key);
return getContentJson().getBoolean(key);
}
/**
......@@ -119,7 +124,7 @@ public class ApiForm {
* @return
*/
public JSONObject getJSONObject(String key) {
return getBizContentJson().getJSONObject(key);
return getContentJson().getJSONObject(key);
}
/**
......@@ -131,7 +136,7 @@ public class ApiForm {
* @return
*/
public JSONArray getJSONArray(String key) {
return getBizContentJson().getJSONArray(key);
return getContentJson().getJSONArray(key);
}
/**
......@@ -158,7 +163,7 @@ public class ApiForm {
* @return
*/
public Map<String, Object> getParamsMap(boolean isSetUserId, String key) {
JSONObject json = getBizContentJson();
JSONObject json = getContentJson();
Map<String, Object> innerMap = json.getInnerMap();
innerMap.put("token", getToken());
if (isSetUserId) {
......
......@@ -117,6 +117,17 @@ public class ApiUtils {
return new ApiResp(form, ApiCodeEnum.METHOD_HANDLER_ERROR);
}
/**
* 传递参数异常
* <p>
* 2016年9月29日 上午11:44:38
*
* @return
*/
public static ApiResp getParamError(ApiForm form) {
return new ApiResp(form, ApiCodeEnum.PARAM_ERROR);
}
public static ApiResp toApiResp(ApiForm form, ResultVo resultVo) {
ApiResp apiResp = new ApiResp(form);
if (resultVo.isSuccess()) {
......
package com.zq.common.utils;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.util.zip.Deflater;
public class WxUserSigUtils {
/**
* 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。
* <p>
* 进入腾讯云云通信[控制台](https://console.cloud.tencent.com/avc ) 创建应用,即可看到 SDKAppId,
* 它是腾讯云用于区分客户的唯一标识。
*/
public static final int SDKAPPID = 1400447523;
/**
* 签名过期时间,建议不要设置的过短
* <p>
* 时间单位:秒
* 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天
*/
private static final int EXPIRETIME = 604800;
/**
* 计算签名用的加密密钥,获取步骤如下:
* <p>
* step1. 进入腾讯云云通信[控制台](https://console.cloud.tencent.com/avc ) ,如果还没有应用就创建一个,
* step2. 单击“应用配置”进入基础配置页面,并进一步找到“帐号体系集成”部分。
* step3. 点击“查看密钥”按钮,就可以看到计算 UserSig 使用的加密的密钥了,请将其拷贝并复制到如下的变量中
* <p>
* 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
* 文档:https://cloud.tencent.com/document/product/269/32688#Server
*/
private static final String SECRETKEY = "da4138b5ed488dbb93de2b2b0206ce9b57629be51d92d73a8c71c710c5bfb5f0";
/**
* 计算 UserSig 签名
* <p>
* 函数内部使用 HMAC-SHA256 非对称加密算法,对 SDKAPPID、userId 和 EXPIRETIME 进行加密。
*
* @note: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
* <p>
* 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
* 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
* 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
* <p>
* 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
* 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
* <p>
* 文档:https://cloud.tencent.com/document/product/269/32688#Server
*/
public static String genUserSig(String userId, Integer expireTime) {
return GenTLSSignature(SDKAPPID, userId, expireTime == null ? EXPIRETIME : expireTime, null, SECRETKEY);
}
/**
* 生成 tls 票据
*
* @param sdkappid 应用的 appid
* @param userId 用户 id
* @param expire 有效期,单位是秒
* @param userbuf 默认填写null
* @param priKeyContent 生成 tls 票据使用的私钥内容
* @return 如果出错,会返回为空,或者有异常打印,成功返回有效的票据
*/
private static String GenTLSSignature(long sdkappid, String userId, long expire, byte[] userbuf, String priKeyContent) {
if (StringUtils.isEmpty(priKeyContent)) {
return "";
}
long currTime = System.currentTimeMillis() / 1000;
JSONObject sigDoc = new JSONObject();
try {
sigDoc.put("TLS.ver", "2.0");
sigDoc.put("TLS.identifier", userId);
sigDoc.put("TLS.sdkappid", sdkappid);
sigDoc.put("TLS.expire", expire);
sigDoc.put("TLS.time", currTime);
} catch (JSONException e) {
e.printStackTrace();
}
String base64UserBuf = null;
if (null != userbuf) {
base64UserBuf = Base64.getEncoder().encodeToString(userbuf);
try {
sigDoc.put("TLS.userbuf", base64UserBuf);
} catch (JSONException e) {
e.printStackTrace();
}
}
String sig = hmacsha256(sdkappid, userId, currTime, expire, priKeyContent, base64UserBuf);
if (sig.length() == 0) {
return "";
}
try {
sigDoc.put("TLS.sig", sig);
} catch (JSONException e) {
e.printStackTrace();
}
Deflater compressor = new Deflater();
compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
compressor.finish();
byte[] compressedBytes = new byte[2048];
int compressedBytesLength = compressor.deflate(compressedBytes);
compressor.end();
return new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength)));
}
private static String hmacsha256(long sdkappid, String userId, long currTime, long expire, String priKeyContent, String base64Userbuf) {
String contentToBeSigned = "TLS.identifier:" + userId + "\n"
+ "TLS.sdkappid:" + sdkappid + "\n"
+ "TLS.time:" + currTime + "\n"
+ "TLS.expire:" + expire + "\n";
if (null != base64Userbuf) {
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
}
try {
byte[] byteKey = priKeyContent.getBytes(StandardCharsets.UTF_8);
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
hmac.init(keySpec);
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
return new String(Base64.getEncoder().encode(byteSig));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
return "";
}
}
private static byte[] base64EncodeUrl(byte[] input) {
byte[] base64 = new String(Base64.getEncoder().encode(input)).getBytes();
for (int i = 0; i < base64.length; ++i)
switch (base64[i]) {
case '+':
base64[i] = '*';
break;
case '/':
base64[i] = '-';
break;
case '=':
base64[i] = '_';
break;
default:
break;
}
return base64;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment