基于 APPKEY 和 APPSECRET 的授权验证

原创
2020/07/27 09:52
阅读数 7.8K

        为了避免对接方多一次登录授权获取 token ,升级了第三方接入接口。由原来的登录获取 token ,每次请求携带 token 获取数据变更为:appkey 和 appsecret 的方式。

        直接上干货,自己捞。(Java 签名工具类)

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Formatter;
import java.util.List;

/**
 * 签名助手
 *
 * @author Ryan
 * @date 2019/9/3 9:48
 */
public class SignatureHelper {
    private static final Logger log = LoggerFactory.getLogger(SignatureHelper.class);
    private static final String HASH_ALGORITHM = "HmacSHA256";

    /**
     * @return
     */
    public static synchronized String nonce() {
        return RandomStringUtils.randomAlphanumeric(8);
    }

    /**
     * @param timestamp
     * @param nonce
     * @param apiKey
     * @return
     */
    public static String generateJoinStr(String timestamp, String nonce, String apiKey) {
        List<String> beforesort = new ArrayList<String>(3);
        beforesort.add(apiKey);
        beforesort.add(timestamp);
        beforesort.add(nonce);

        // 排序
        beforesort.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                try {
                    String s1 = new String(o1.toString().getBytes("GB2312"), "ISO-8859-1");
                    String s2 = new String(o2.toString().getBytes("GB2312"), "ISO-8859-1");
                    return s1.compareTo(s2);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return 0;
            }
        });

        StringBuilder aftersort = new StringBuilder();
        for (int i = 0; i < beforesort.size(); i++) {
            aftersort.append(beforesort.get(i));
        }

        return aftersort.toString();
    }


    /**
     * @param appKey
     * @param appSecret
     * @return
     */
    private static String genEncryptString(String appKey, String appSecret) throws NoSuchAlgorithmException, InvalidKeyException {
        Key secretKey = new SecretKeySpec(appSecret.getBytes(), HASH_ALGORITHM);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);

        //完成hamc-sha256签名
        final byte[] hmac = mac.doFinal(appKey.getBytes());
        StringBuilder sb = new StringBuilder(hmac.length * 2);
        Formatter formatter = new Formatter(sb);

        for (byte b : hmac) {
            formatter.format("%02x", b);
        }

        //完成16进制编码
        return sb.toString();
    }


    /**
     * @param apiKey
     * @param timestamp
     * @param nonce
     * @param signature
     * @return
     */
    public static String sign(String apiKey, String timestamp, String nonce, String signature) {
        return String.format("appkey=%s,timestamp=%s,nonceStr=%s,sign=%s", apiKey, timestamp, nonce, signature);
    }

    /**
     * @param apiKey
     * @param appSecret
     * @return
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     */
    public static String token(String apiKey, String timestamp, String nonce, String appSecret) throws InvalidKeyException, NoSuchAlgorithmException {

        String genjoinstr = generateJoinStr(timestamp, nonce, apiKey);
        String signature = genEncryptString(genjoinstr, appSecret);

        String sign = sign(apiKey, timestamp, nonce, signature);
        return DigestUtils.md5Hex(sign);
    }

    /**
     * @param appkey
     * @param timestamp
     * @param nonce
     * @param token
     * @return
     */
    public static boolean matchSign(String appkey, String appSecret, String timestamp, String nonce, String token) {

        try {
            String t = token(appkey, timestamp, nonce, appSecret);
            return token.equals(t);
        } catch (InvalidKeyException e) {
            log.error("InvalidKeyException", e);
        } catch (NoSuchAlgorithmException e) {
            log.error("NoSuchAlgorithmException", e);
        }
        return false;
    }


    /**
     * @param apiKey
     * @return
     */
    public static String genauthorization(String apiKey, String appSecret) throws InvalidKeyException, NoSuchAlgorithmException {

        String nonce = nonce();
        String timestamp = Long.toString(System.currentTimeMillis());
        String genjoinstr = generateJoinStr(timestamp, nonce, apiKey);
        String signature = genEncryptString(genjoinstr, appSecret);

        return "appkey=" + apiKey + ",timestamp=" + timestamp + ",nonce=" + nonce + ",sign=" + signature;
    }
}

为了方便测试,写个 postman ,记录一下信息:

/**
 * datetime 	2020年7月21日  11:10
 * author		Ryan
 * description	授权 Header 管理;
 */

var appKey = "depot_4f34ft4rej76k6j3395072"
var appSecret='7RL2pPavM8E2f9ctM4DNq6uXCFueuJ6X'


pm.globals.unset("appkey");
pm.globals.unset("nonceStr");
pm.globals.unset("token");
pm.globals.unset("timestamp");


/** ************************************************************************************************************************* */

//生成随机字符串
function randomString(len) {
	len = len || 32;
	var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefghijklmnopqrstuvwxyz23456789';    
	var maxLen = $chars.length;
	var str = '';
	for (i = 0; i < len; i++) { 
		str += $chars.charAt(Math.floor(Math.random() * maxLen));
	}
	return str;
}

var nonceStr = randomString(8);
var timestamp = new Date().getTime() + "";

var joinStr = [appKey, nonceStr, timestamp];
var generateJoinStr = joinStr.sort((a, b) => a.localeCompare(b)).join("");


var hmacSHA256 = CryptoJS.HmacSHA256(generateJoinStr, appSecret);
var signature =hmacSHA256.toString(CryptoJS.enc.Hex)

var sign = "appkey=" + appKey + ",timestamp=" + timestamp + ",nonceStr="+nonceStr + ",sign=" +signature;
var token = CryptoJS.MD5(sign) + "";





pm.globals.set("appkey", appKey);
pm.globals.set("nonceStr", nonceStr);
pm.globals.set("token", token);
pm.globals.set("timestamp", timestamp);

console.log("========================================================================================================");
console.log("appkey=" + appKey);
console.log("appSecret=" + appSecret);
console.log("nonceStr=" + nonceStr);
console.log("timestamp=" + timestamp);
console.log("generateJoinStr=" + generateJoinStr);
console.log("sign=" + sign);
console.log("token : " + token);

 (注意: postman 的 pre-request script 在做加密的时候,偶尔会出现加密数据不稳定的情况,原因暂且没有定位到,待定位到后再更新。

展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部