天天看点

对外接口加密

package com.yonyou.cyx.datacenter.service.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMethod;

import com.alibaba.fastjson.JSON;
import com.xiaoleilu.hutool.util.StrUtil;
import com.yonyou.cyx.cyxframework.util.MD5Util;
import com.yonyou.cyx.framework.bean.dto.framework.RestResultResponse;
import com.yonyou.cyx.framework.bean.dto.framework.ResultBean;

@WebFilter(urlPatterns = "/**/**", filterName = "ExosystemFilter")
public class ExosystemFilter implements Filter {

   @Autowired
   private StringRedisTemplate redisTemplate;

   @Autowired
   private Environment env;

   /**
    * 日志
    */
   private static Logger logger = LoggerFactory.getLogger(ExosystemFilter.class);

   @Override
   public void init(FilterConfig filterConfig) throws ServletException {
      logger.info("ExosystemFilter init!");
   }

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
         throws IOException, ServletException {
      @SuppressWarnings("unchecked")
      RestResultResponse<Integer> result = new RestResultResponse<Integer>().success(false);
      result.setResultCode(ResultBean.VALID_FAILD);
      response.setContentType("application/json;charset=UTF-8");
      HttpServletRequest httpServletRequest = (HttpServletRequest) request;
      Charset utf8charset = Charset.forName("UTF-8");
      try {
         // 接口只支持post请求
         if (RequestMethod.POST.name().equalsIgnoreCase(httpServletRequest.getMethod())) {
            ServletRequest requestWrapper = new PostBodyRequestWrapper(httpServletRequest);
            String body = HttpHelper.getBodyString(requestWrapper);
            if (StrUtil.isBlank(body)) {
               result.setErrMsg("RequestBody不能为空");
               response.getOutputStream().write(JSON.toJSONString(result).getBytes(utf8charset));
               return;
            } else {
               String appid = httpServletRequest.getHeader("appid");
               String nonce = httpServletRequest.getHeader("nonce");
               String occurtime = httpServletRequest.getHeader("occurtime");
               String sign = httpServletRequest.getHeader("sign");
               logger.info("签名认证参数,appid:{}, nonce:{}, occurtime:{}, sign:{}", appid, nonce, occurtime, sign);
               if (StrUtil.isBlank(appid) || StrUtil.isBlank(nonce) || StrUtil.isBlank(occurtime)
                     || StrUtil.isBlank(sign)) {
                  result.setErrMsg("认证失败,必须参数不能为空");
                  response.getOutputStream().write(JSON.toJSONString(result).getBytes(utf8charset));
                  return;
               } else {
                  // 根据appId获取appKey
                  String appKey = env.getProperty("appKey." + appid);
                  // 不存在
                  if (StrUtil.isBlank(appKey)) {
                     // 认证失败
                     result.setResultCode(401);
                     result.setErrMsg("认证失败,appId不合法");
                     response.getOutputStream()
                           .write(JSON.toJSONString(result).getBytes(utf8charset));
                     return;
                  }
                  // 生成签名
                  String signLocal = appKey + nonce + occurtime;
                  logger.info("加密前签名:" ,signLocal);
                  signLocal = MD5Util.md5(signLocal).toLowerCase();
                  logger.info("加密后签名:" ,signLocal);
                  if (signLocal.equals(sign)) {
                     String oldSign = redisTemplate.opsForValue().get(appid + sign);
                     // 判断签名是否重复调用
                     if (StrUtil.isNotBlank(oldSign)) {
                        result.setResultCode(401);
                        result.setErrMsg("认证失败,签名重复使用");
                        response.getOutputStream()
                              .write(JSON.toJSONString(result).getBytes(utf8charset));
                        return;
                     } else {
                        // 保存认证签名
                        logger.debug("请求签名:{}", sign);
                        redisTemplate.opsForValue().set(appid + sign, sign, 24 * 3600L, TimeUnit.SECONDS);
                     }
                  } else {
                     result.setResultCode(401);
                     result.setErrMsg("认证失败,签名加密错误");
                     response.getOutputStream()
                           .write(JSON.toJSONString(result).getBytes(utf8charset));
                     return;
                  }
               }
               chain.doFilter(requestWrapper, response);
            }
         } else {
            result.setErrMsg("API只支持POST请求");
            response.getOutputStream().write(JSON.toJSONString(result).getBytes(utf8charset));
            return;
         }
      } catch (Exception e) {
         logger.error("API认证失败:", e);
         result.setErrMsg("认证失败," + e.getMessage());
         response.getOutputStream().write(JSON.toJSONString(result).getBytes(utf8charset));
         return;
      }
   }

   @Override
   public void destroy() {

   }

    public static void main(String[] args) throws InterruptedException, NoSuchAlgorithmException, UnsupportedEncodingException {
        long time = new Date().getTime();
        String nonce = "4465";
        String sign = "0sTUkoug6HneoxFkJjGc_EYJ5WIIBcCD" + nonce + time;
//      System.out.println(nonce);
//        System.out.println(time);
//        System.out.println(sign);
//      System.out.println(MD5Util.md5(sign).toLowerCase());
    }
}      

转载于:https://www.cnblogs.com/jabez1992/p/11339447.html