
io.github.wslxm.springbootplus2.utils.XjSignUtil Maven / Gradle / Ivy
package io.github.wslxm.springbootplus2.utils;
import io.github.wslxm.springbootplus2.core.utils.XjPropUtil;
import lombok.extern.slf4j.Slf4j;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
/**
* @author wangsong
* 参数验证签名
*/
@Slf4j
public class XjSignUtil {
private static String APP_KEY = null;
private static String SECRET_KEY = null;
private static Long TIME_OUT = null;
// 默认值
private final static String DEFAULT_APP_KEY = "xijia";
private final static String DEFAULT_SECRET_KEY = "xijia@qwer";
private final static Long DEFAULT_TIME_OUT = 60L;
/**
* 字符编码
*/
private final static String INPUT_CHARSET = "UTF-8";
/**
* 验签 key
*/
public final static String SIGN = "sign";
/**
* 时间戳 key
*/
public final static String TIMESTAMP = "timestamp";
/**
* body 参数的参数key
*/
public final static String BODY = "body";
private static String getAppKey() {
if (APP_KEY == null) {
Object appKey = XjPropUtil.findByKey("secure.sign.appKey");
APP_KEY = appKey != null ? appKey.toString() : DEFAULT_APP_KEY;
}
return APP_KEY;
}
private static String getSecretKey() {
if (SECRET_KEY == null) {
Object secretKey = XjPropUtil.findByKey("secure.sign.secretKey");
SECRET_KEY = secretKey != null ? secretKey.toString() : DEFAULT_SECRET_KEY;
}
return SECRET_KEY;
}
private static Long getTimeOut() {
if (TIME_OUT == null) {
Object timeout = XjPropUtil.findByKey("secure.sign.timeout");
TIME_OUT = timeout != null ? Long.parseLong(timeout.toString()) : DEFAULT_TIME_OUT;
}
return TIME_OUT;
}
/**
* 根据反馈回来的信息,生成签名结果 current=1&fullName= &id=&size=10×tamp=1618538349587&username=
*
* @param params 通知返回来的参数数组
* @return 验证结果
*/
public static boolean verify(Map params) {
// 获取签名参数
boolean isVerify = false;
String sign = "";
if (params.containsKey(SIGN)) {
sign = params.get(SIGN);
// 过滤空值sign
Map sParaNew = paraFilter(params);
// 获取待签名字符串
String preSignStr = createLinkString(sParaNew, false);
log.debug("加签参数:{}", preSignStr);
// 获得签名验证结果
String mysign = XjSignMd5Util.md5(getAppKey() + preSignStr + getSecretKey());
if (mysign.equals(sign)) {
isVerify = true;
}
}
return isVerify;
}
/**
* 验证是否超时
* timestamp = 请求时间(秒)
*
* @return 验证结果
*/
public static boolean isTimeVerify(Long timestamp) {
// 判断请求是否超时
long currentTimeMillis = System.currentTimeMillis();
return timestamp != null && (currentTimeMillis - Long.parseLong(timestamp.toString())) < (getTimeOut() * 1000L);
}
/**
* 请求参数Map转换验证Map
*
* SignUtil.toVerifyMap(request.getParameterMap(), false);
* 参数根据字母大小写排序
*
*
* @param requestParams 请求参数Map
* @param charset 是否要转utf8编码
* @return
*/
public static Map toVerifyMap(Map requestParams, boolean charset) {
Map params = new HashMap<>(16);
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
if (charset) {
valueStr = getContentString(valueStr, INPUT_CHARSET);
}
params.put(name, valueStr);
}
return params;
}
/**
* 除去数组中的空值和签名参数
*
* @param sArray 签名参数组
* @return 去掉空值与签名参数后的新签名参数组
*/
public static Map paraFilter(Map sArray) {
Map result = new HashMap<>(16);
if (sArray == null || sArray.size() <= 0) {
return result;
}
for (String key : sArray.keySet()) {
String value = sArray.get(key);
//|| "".equals(value)
if (value == null || key.equalsIgnoreCase(SIGN)) {
continue;
}
result.put(key, value);
}
return result;
}
/**
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
*
* @param params 需要排序并参与字符拼接的参数组
* @param encode 是否需要UrlEncode
* @return 拼接后字符串
*/
public static String createLinkString(Map params, boolean encode) {
List keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (encode) {
value = urlEncode(value, INPUT_CHARSET);
}
if (i == keys.size() - 1) {
// 拼接时,不包括最后一个&字符
sb.append(key).append("=").append(value);
} else {
sb.append(key).append("=").append(value).append("&");
}
}
return sb.toString();
}
/**
* 编码转换
*
* @param content
* @param charset
* @return
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
/**
* 编码转换
*
* @param content
* @param charset
* @return
*/
private static String getContentString(String content, String charset) {
if (charset == null || "".equals(charset)) {
return new String(content.getBytes());
}
try {
return new String(content.getBytes("ISO-8859-1"), charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
/**
* URL转码
*
* @param content
* @param charset
* @return
*/
private static String urlEncode(String content, String charset) {
try {
return URLEncoder.encode(content, charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy