加解密工具并发问题

最近在使用javax.crypto.Mac做加解密时,发现用压测工具做高并发的压测时会出问题。查了一下原因:为了优化性能,全局只提前为每一秘钥生成了一个Mac类,而这个类在进行计算时会改变内部数据结构,所以在高并发的时候会报错。查到和想到的类似问题解决办法有两个:

1、每次使用时,clone一个Mac类

2、使用threadlocal为每个线程新建一个Mac类

下面是我用threadlocal的例子:

import com.google.common.cache.Cache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;

/**
 * 签名工具
 */
@Slf4j
public class SignUtil {
    private static ThreadLocal<Cache<String, Optional<Mac>>> macThreadLocal = ThreadLocal.withInitial(() -> CacheBuilder.newBuilder().maximumSize(1000).build());

    /**
     * 计算签名
     *
     * @param secret APP密钥
     * @param method HttpMethod
     * @param path
     * @param headers
     * @param querys
     * @param bodys
     * @param signHeaderPrefixList 自定义参与签名Header前缀
     * @return 签名后的字符串
     */
    public static String sign(String secret, String method, String path, 
    							Map<String, String> headers, 
    							Map<String, String> querys, 
    							Map<String, String> bodys, 
    							List<String> signHeaderPrefixList) {
        try {
            Mac hmacSha256 = macThreadLocal.get().get(secret, () -> {
                Mac hmacSha2561 = null;
                try {
                    hmacSha2561 = Mac.getInstance(Constants.HMAC_SHA256);
                    byte[] keyBytes = secret.getBytes(Constants.ENCODING);
                    hmacSha2561.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, Constants.HMAC_SHA256));
                } catch (Exception e) {
                    log.error("get hmacSha256 error", e);
                }

                return Optional.ofNullable(hmacSha2561);
            }).get();

            return new String(Base64.encodeBase64(
                    hmacSha256.doFinal(buildStringToSign(method, path, headers, querys, bodys, signHeaderPrefixList)
                            .getBytes(Constants.ENCODING))),
                    Constants.ENCODING);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值