ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

API网关验签

2021-07-03 17:03:33  阅读:275  来源: 互联网

标签:nonce 网关 const String timestamp headers API signature 验签


在前后端开发的过程中,我们一般在请求头中添加一些信息来保证验证请求身份,这里涉及到四个字段值:

appId: 软件Id

nonce:随机字符串

timestamp:时间戳

signature:签名

代码如下:

@Component
public class CommonApiAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String httpMethod = request.getMethodValue();
            String httpUri = request.getURI().getPath();
            //特定请求不进行验签
            if (httpUri.contains("/v2/api-docs")){
                return chain.filter(exchange.mutate().request(request.mutate().build()).build());
            }

            HttpHeaders headers = request.getHeaders();
            String signature = headers.getFirst(Constant.SIGNATURE);
            String nonce = headers.getFirst(Constant.NONCE);
            String appId = headers.getFirst(Constant.APP_ID);

            if (StringUtils.isAllBlank(signature, nonce, headers.getFirst(Constant.TIMESTAMP))) {
                return ApiAuthUtils.checkSign(exchange, WrapMapper.illegalArgument("signature|nonce|timestamp不能为空"), HttpStatus.BAD_REQUEST);
            }
            long timestamp = Long.parseLong(headers.getFirst(Constant.TIMESTAMP));

            // 验证如果传过来的时间戳超过1分钟,直接返回false
            if ((System.currentTimeMillis() - timestamp) / 1000 > 60) {
                return ApiAuthUtils.checkSign(exchange, WrapMapper.wrap(403, "timestamp overtime"), HttpStatus.FORBIDDEN);
            }

            boolean result = CryptUtils.validateSignature(appId, timestamp, nonce, httpMethod, httpUri, signature);
            if (!result) {
                return ApiAuthUtils.checkSign(exchange, WrapMapper.wrap(403, "Forbidden"), HttpStatus.FORBIDDEN);
            }

            Builder mutate = request.mutate();
            return chain.filter(exchange.mutate().request(mutate.build()).build());
        };
    }
}

验签算法:

 public static boolean validateSignature(String appId, long timestamp, String nonce, String httpmethod,String httpurl, String signature) {
        String str = appId + "|" + nonce + "|" + timestamp + "|" + httpmethod.concat("|").concat(httpurl);
        String encryptBASE64 = encryptBASE64(sha256(str.getBytes()));
        logger.debug("signature: {}, encryptBASE64: {}", signature, encryptBASE64);
        return Arrays.equals(encryptBASE64.getBytes(), signature.getBytes());
    }

 

前端在发送请求时也需要在请求头加入对应信息,如:

request.interceptors.request.use(config => {
  const token = storage.get(ACCESS_TOKEN)
  if (token) {
    config.headers['Access-Token'] = token
  }
  const url = config.url.split('?')[0]
  const appId = '123456789'
  const timestamp = new Date().getTime()
  const nonce = generateNonce(timestamp)
  const signature = generateSignature(appId, timestamp, nonce, config.method.toUpperCase(), url)
  config.headers.appId = appId
  config.headers.signature = signature
  config.headers.nonce = nonce
  config.headers.timestamp = timestamp
  return config
}, errorHandler)

export const generateSignature = (appId, timestamp, nonce, httpMethod, httpURL) => {
  const str = appId + '|' + nonce + '|' + timestamp + '|' + httpMethod + '|' + httpURL
  let result = SHA256(str)
  if (result) {
    result = strToBase64(result)
  }
  return result
}

export const generateNonce = (theServerTime) => {
  const randomNumber = []
  for (let i = 0; i < 8; i++) {
    const oneRandom = random(-128, 127)
    randomNumber.push(oneRandom)
  }
  let timeStamp = Math.floor(new Date().getTime() / 60000)
  if (theServerTime !== 0) {
    timeStamp = Math.floor(theServerTime / 60000)
  }

  const nt = []
  nt[3] = timeStamp & 0xff
  nt[2] = (timeStamp >> 8) & 0xff
  nt[1] = (timeStamp >> 16) & 0xff
  nt[0] = (timeStamp >> 24) & 0xff
  for (let x = 0; x < nt.length; x++) {
    randomNumber.push(nt[x])
  }

  return bytesToBase64(randomNumber)
}

 

标签:nonce,网关,const,String,timestamp,headers,API,signature,验签
来源: https://www.cnblogs.com/wlong-blog/p/14966731.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有