| | |
| | | import com.java110.api.smo.IApiServiceSMO; |
| | | import com.java110.common.cache.AppRouteCache; |
| | | import com.java110.common.cache.MappingCache; |
| | | import com.java110.common.constant.*; |
| | | import com.java110.common.exception.*; |
| | | import com.java110.common.constant.CommonConstant; |
| | | import com.java110.common.constant.KafkaConstant; |
| | | import com.java110.common.constant.MappingConstant; |
| | | import com.java110.common.constant.ResponseConstant; |
| | | import com.java110.common.constant.ServiceCodeConstant; |
| | | import com.java110.common.exception.BusinessException; |
| | | import com.java110.common.exception.DecryptException; |
| | | import com.java110.common.exception.InitConfigDataException; |
| | | import com.java110.common.exception.ListenerExecuteException; |
| | | import com.java110.common.exception.NoAuthorityException; |
| | | import com.java110.common.exception.SMOException; |
| | | import com.java110.common.kafka.KafkaFactory; |
| | | import com.java110.common.log.LoggerEngine; |
| | | import com.java110.common.util.DateUtil; |
| | | import com.java110.common.util.StringUtil; |
| | | import com.java110.core.client.RestTemplate; |
| | | import com.java110.core.context.ApiDataFlow; |
| | | import com.java110.core.context.DataFlow; |
| | | import com.java110.core.factory.AuthenticationFactory; |
| | |
| | | import com.java110.entity.center.AppService; |
| | | import com.java110.entity.center.DataFlowLinksCost; |
| | | import com.java110.event.service.api.ServiceDataFlowEventPublishing; |
| | | import com.java110.service.smo.IQueryServiceSMO; |
| | | import org.apache.commons.lang3.math.NumberUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | |
| | | //@Transactional |
| | | public class ApiServiceSMOImpl extends LoggerEngine implements IApiServiceSMO { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(ApiServiceSMOImpl.class); |
| | | private static Logger logger = LoggerFactory.getLogger(ApiServiceSMOImpl.class); |
| | | |
| | | @Autowired |
| | | private RestTemplate restTemplate; |
| | |
| | | @Autowired |
| | | private RestTemplate restTemplateNoLoadBalanced; |
| | | |
| | | @Autowired |
| | | private IQueryServiceSMO queryServiceSMOImpl; |
| | | |
| | | /** |
| | | * 服务调度 |
| | | * 服务调度 |
| | | * |
| | | * @param reqJson 请求报文json |
| | | * @param headers |
| | | * @return |
| | | * @throws SMOException |
| | | */ |
| | | @Override |
| | | public ResponseEntity<String> service(String reqJson, Map<String, String> headers) throws SMOException{ |
| | | public ResponseEntity<String> service(String reqJson, Map<String, String> headers) throws SMOException { |
| | | |
| | | ApiDataFlow dataFlow = null; |
| | | |
| | |
| | | |
| | | try { |
| | | //在post和 put 时才存在报文加密的情况 |
| | | if("POST,PUT".contains(headers.get(CommonConstant.HTTP_METHOD))){ |
| | | reqJson = decrypt(reqJson,headers); |
| | | if ("POST,PUT".contains(headers.get(CommonConstant.HTTP_METHOD))) { |
| | | reqJson = decrypt(reqJson, headers); |
| | | } |
| | | |
| | | //1.0 创建数据流 |
| | | dataFlow = DataFlowFactory.newInstance(ApiDataFlow.class).builder(reqJson,headers); |
| | | dataFlow = DataFlowFactory.newInstance(ApiDataFlow.class).builder(reqJson, headers); |
| | | |
| | | //2.0 加载配置信息 |
| | | initConfigData(dataFlow); |
| | |
| | | |
| | | responseEntity = dataFlow.getResponseEntity(); |
| | | |
| | | } catch (DecryptException e){ //解密异常 |
| | | responseEntity = new ResponseEntity<String>("解密异常:"+e.getMessage(), HttpStatus.NON_AUTHORITATIVE_INFORMATION); |
| | | }catch (BusinessException e) { |
| | | responseEntity = new ResponseEntity<String>("业务处理异常:"+e.getMessage(), HttpStatus.BAD_REQUEST); |
| | | } catch (DecryptException e) { //解密异常 |
| | | responseEntity = new ResponseEntity<String>("解密异常:" + e.getMessage(), HttpStatus.NON_AUTHORITATIVE_INFORMATION); |
| | | } catch (BusinessException e) { |
| | | responseEntity = new ResponseEntity<String>("业务处理异常:" + e.getMessage(), HttpStatus.BAD_REQUEST); |
| | | } catch (NoAuthorityException e) { |
| | | responseEntity = new ResponseEntity<String>("鉴权失败:"+e.getMessage(), HttpStatus.UNAUTHORIZED); |
| | | } catch (InitConfigDataException e){ |
| | | responseEntity = new ResponseEntity<String>("初始化失败:"+e.getMessage(), HttpStatus.BAD_REQUEST); |
| | | }catch (Exception e) { |
| | | logger.error("内部异常:",e); |
| | | responseEntity = new ResponseEntity<String>("内部异常:"+e.getMessage()+e.getLocalizedMessage(), HttpStatus.INTERNAL_SERVER_ERROR); |
| | | responseEntity = new ResponseEntity<String>("鉴权失败:" + e.getMessage(), HttpStatus.UNAUTHORIZED); |
| | | } catch (InitConfigDataException e) { |
| | | responseEntity = new ResponseEntity<String>("初始化失败:" + e.getMessage(), HttpStatus.BAD_REQUEST); |
| | | } catch (Exception e) { |
| | | logger.error("内部异常:", e); |
| | | responseEntity = new ResponseEntity<String>("内部异常:" + e.getMessage() + e.getLocalizedMessage(), HttpStatus.INTERNAL_SERVER_ERROR); |
| | | |
| | | } finally { |
| | | if(dataFlow != null) { |
| | | if (dataFlow != null) { |
| | | //这里记录日志 |
| | | Date endDate = DateUtil.getCurrentDate(); |
| | | |
| | |
| | | //处理返回报文鉴权 |
| | | //AuthenticationFactory.putSign(dataFlow); |
| | | } |
| | | if (responseEntity == null){ |
| | | if (responseEntity == null) { |
| | | //resJson = encrypt(responseJson.toJSONString(),headers); |
| | | responseEntity = new ResponseEntity<String>(resJson, HttpStatus.OK); |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 抒写返回头信息 |
| | | * |
| | | * @param dataFlow |
| | | */ |
| | | private void putResponseHeader(DataFlow dataFlow,Map<String,String> headers) { |
| | | private void putResponseHeader(DataFlow dataFlow, Map<String, String> headers) { |
| | | headers.put("responseTime", DateUtil.getDefaultFormateTimeString(new Date())); |
| | | headers.put("transactionId",dataFlow.getTransactionId()); |
| | | headers.put("transactionId", dataFlow.getTransactionId()); |
| | | } |
| | | |
| | | /** |
| | | * 解密 |
| | | * |
| | | * @param reqJson |
| | | * @return |
| | | */ |
| | | private String decrypt(String reqJson,Map<String,String> headers) throws DecryptException{ |
| | | private String decrypt(String reqJson, Map<String, String> headers) throws DecryptException { |
| | | try { |
| | | if (MappingConstant.VALUE_ON.equals(headers.get(CommonConstant.ENCRYPT))) { |
| | | logger.debug("解密前字符:" + reqJson); |
| | | reqJson = new String(AuthenticationFactory.decrypt(reqJson.getBytes("UTF-8"), AuthenticationFactory.loadPrivateKey(MappingConstant.KEY_PRIVATE_STRING) |
| | | , NumberUtils.isNumber(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) ? Integer.parseInt(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) : |
| | | Integer.parseInt(MappingCache.getValue(MappingConstant.KEY_DEFAULT_DECRYPT_KEY_SIZE))),"UTF-8"); |
| | | reqJson = new String(AuthenticationFactory.decrypt(reqJson.getBytes("UTF-8"), |
| | | AuthenticationFactory.loadPrivateKey(MappingConstant.KEY_PRIVATE_STRING) |
| | | , NumberUtils.isNumber(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) ? |
| | | Integer.parseInt(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) : |
| | | Integer.parseInt(MappingCache.getValue(MappingConstant.KEY_DEFAULT_DECRYPT_KEY_SIZE))), "UTF-8"); |
| | | logger.debug("解密后字符:" + reqJson); |
| | | } |
| | | }catch (Exception e){ |
| | | throw new DecryptException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR,"解密失败"); |
| | | } catch (Exception e) { |
| | | throw new DecryptException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "解密失败"); |
| | | } |
| | | |
| | | return reqJson; |
| | |
| | | |
| | | /** |
| | | * 加密 |
| | | * |
| | | * @param resJson |
| | | * @param headers |
| | | * @return |
| | | */ |
| | | private String encrypt(String resJson,Map<String,String> headers){ |
| | | private String encrypt(String resJson, Map<String, String> headers) { |
| | | try { |
| | | if (MappingConstant.VALUE_ON.equals(headers.get(CommonConstant.ENCRYPT))) { |
| | | logger.debug("加密前字符:" + resJson); |
| | | resJson = new String(AuthenticationFactory.encrypt(resJson.getBytes("UTF-8"), AuthenticationFactory.loadPubKey(MappingConstant.KEY_PUBLIC_STRING) |
| | | , NumberUtils.isNumber(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) ? Integer.parseInt(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) : |
| | | Integer.parseInt(MappingCache.getValue(MappingConstant.KEY_DEFAULT_DECRYPT_KEY_SIZE))),"UTF-8"); |
| | | Integer.parseInt(MappingCache.getValue(MappingConstant.KEY_DEFAULT_DECRYPT_KEY_SIZE))), "UTF-8"); |
| | | logger.debug("加密后字符:" + resJson); |
| | | } |
| | | }catch (Exception e){ |
| | | logger.error("加密失败:",e); |
| | | } catch (Exception e) { |
| | | logger.error("加密失败:", e); |
| | | } |
| | | return resJson; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | if (appRoutes == null) { |
| | | //添加耗时 |
| | | DataFlowFactory.addCostTime(dataFlow, "initConfigData", "加载配置耗时", startDate); |
| | | throw new InitConfigDataException(ResponseConstant.RESULT_CODE_INNER_ERROR,"当前没有获取到AppId对应的信息,appId = "+dataFlow.getAppId()); |
| | | throw new InitConfigDataException(ResponseConstant.RESULT_CODE_INNER_ERROR, "当前没有获取到AppId对应的信息,appId = " + dataFlow.getAppId()); |
| | | } |
| | | for(AppRoute appRoute: appRoutes) { |
| | | for (AppRoute appRoute : appRoutes) { |
| | | dataFlow.addAppRoutes(appRoute); |
| | | } |
| | | // |
| | | if("-1".equals(dataFlow.getDataFlowId()) || StringUtil.isNullOrNone(dataFlow.getDataFlowId())){ |
| | | if ("-1".equals(dataFlow.getDataFlowId()) || StringUtil.isNullOrNone(dataFlow.getDataFlowId())) { |
| | | dataFlow.setDataFlowId(GenerateCodeFactory.getDataFlowId()); |
| | | } |
| | | |
| | |
| | | private void judgeAuthority(ApiDataFlow dataFlow) throws NoAuthorityException { |
| | | Date startDate = DateUtil.getCurrentDate(); |
| | | |
| | | if (StringUtil.isNullOrNone(dataFlow.getAppId()) || dataFlow.getAppRoutes().size() == 0 ) { |
| | | if (StringUtil.isNullOrNone(dataFlow.getAppId()) || dataFlow.getAppRoutes().size() == 0) { |
| | | //添加耗时 |
| | | DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate); |
| | | throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "APP_ID 为空或不正确"); |
| | |
| | | throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "TRANSACTION_ID 不能为空"); |
| | | } |
| | | |
| | | if(!StringUtil.isNullOrNone(dataFlow.getAppRoutes().get(0).getSecurityCode())){ |
| | | if (!StringUtil.isNullOrNone(dataFlow.getAppRoutes().get(0).getSecurityCode())) { |
| | | String sign = AuthenticationFactory.apiDataFlowMd5(dataFlow); |
| | | if(!sign.equals(dataFlow.getReqSign().toLowerCase())){ |
| | | if (!sign.equals(dataFlow.getReqSign().toLowerCase())) { |
| | | throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "签名失败"); |
| | | } |
| | | } |
| | |
| | | throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "requestTime 格式不对,遵循yyyyMMddHHmmss格式"); |
| | | } |
| | | //用户ID校验 |
| | | if (StringUtil.isNullOrNone(dataFlow.getUserId())){ |
| | | throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "USER_ID 不能为空"); |
| | | if (StringUtil.isNullOrNone(dataFlow.getUserId())) { |
| | | throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "USER_ID 不能为空"); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | //检查黑名单 |
| | | List<String> backListIp = dataFlow.getAppRoutes().get(0).getBackListIp(); |
| | | if (backListIp != null && backListIp.size() > 0&& backListIp.contains(dataFlow.getIp())) { |
| | | if (backListIp != null && backListIp.size() > 0 && backListIp.contains(dataFlow.getIp())) { |
| | | //添加耗时 |
| | | DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate); |
| | | throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "当前IP被限制不能访问服务"); |
| | |
| | | //拿到当前服务 |
| | | AppService appService = DataFlowFactory.getService(dataFlow, dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE)); |
| | | //这里对透传类处理 |
| | | if("NT".equals(appService.getIsInstance())){ |
| | | if ("NT".equals(appService.getIsInstance())) { |
| | | //如果是透传类 请求方式必须与接口提供方调用方式一致 |
| | | String httpMethod = dataFlow.getRequestCurrentHeaders().get(CommonConstant.HTTP_METHOD); |
| | | if(!appService.getMethod().equals(httpMethod)) { |
| | | if (!appService.getMethod().equals(httpMethod)) { |
| | | throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR, |
| | | "服务【" + appService.getServiceCode() + "】调用方式不对请检查,当前请求方式为:"+httpMethod); |
| | | "服务【" + appService.getServiceCode() + "】调用方式不对请检查,当前请求方式为:" + httpMethod); |
| | | } |
| | | dataFlow.setApiCurrentService(ServiceCodeConstant.SERVICE_CODE_DO_SERVICE_TRANSFER); |
| | | }else{ |
| | | } else { |
| | | dataFlow.setApiCurrentService(dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE)); |
| | | } |
| | | ServiceDataFlowEventPublishing.multicastEvent(dataFlow,appService); |
| | | ServiceDataFlowEventPublishing.multicastEvent(dataFlow, appService); |
| | | DataFlowFactory.addCostTime(dataFlow, "invokeBusinessSystem", "调用下游系统耗时", startDate); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 保存日志信息 |
| | | * |
| | | * @param requestJson |
| | | */ |
| | | private void saveLogMessage(String requestJson,String responseJson){ |
| | | private void saveLogMessage(String requestJson, String responseJson) { |
| | | |
| | | try{ |
| | | if(MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.KEY_LOG_ON_OFF))){ |
| | | try { |
| | | if (MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.KEY_LOG_ON_OFF))) { |
| | | JSONObject log = new JSONObject(); |
| | | log.put("request",requestJson); |
| | | log.put("response",responseJson); |
| | | KafkaFactory.sendKafkaMessage(KafkaConstant.TOPIC_LOG_NAME,"",log.toJSONString()); |
| | | log.put("request", requestJson); |
| | | log.put("response", responseJson); |
| | | KafkaFactory.sendKafkaMessage(KafkaConstant.TOPIC_LOG_NAME, "", log.toJSONString()); |
| | | } |
| | | }catch (Exception e){ |
| | | logger.error("报错日志出错了,",e); |
| | | } catch (Exception e) { |
| | | logger.error("报错日志出错了,", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 保存耗时信息 |
| | | * |
| | | * @param dataFlow |
| | | */ |
| | | private void saveCostTimeLogMessage(DataFlow dataFlow){ |
| | | try{ |
| | | if(MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.KEY_COST_TIME_ON_OFF))){ |
| | | private void saveCostTimeLogMessage(DataFlow dataFlow) { |
| | | try { |
| | | if (MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.KEY_COST_TIME_ON_OFF))) { |
| | | List<DataFlowLinksCost> dataFlowLinksCosts = dataFlow.getLinksCostDates(); |
| | | JSONObject costDate = new JSONObject(); |
| | | JSONArray costDates = new JSONArray(); |
| | | JSONObject newObj = null; |
| | | for(DataFlowLinksCost dataFlowLinksCost : dataFlowLinksCosts){ |
| | | for (DataFlowLinksCost dataFlowLinksCost : dataFlowLinksCosts) { |
| | | newObj = JSONObject.parseObject(JSONObject.toJSONString(dataFlowLinksCost)); |
| | | newObj.put("dataFlowId",dataFlow.getDataFlowId()); |
| | | newObj.put("transactionId",dataFlow.getTransactionId()); |
| | | newObj.put("dataFlowId", dataFlow.getDataFlowId()); |
| | | newObj.put("transactionId", dataFlow.getTransactionId()); |
| | | costDates.add(newObj); |
| | | } |
| | | costDate.put("costDates",costDates); |
| | | costDate.put("costDates", costDates); |
| | | |
| | | KafkaFactory.sendKafkaMessage(KafkaConstant.TOPIC_COST_TIME_LOG_NAME,"",costDate.toJSONString()); |
| | | KafkaFactory.sendKafkaMessage(KafkaConstant.TOPIC_COST_TIME_LOG_NAME, "", costDate.toJSONString()); |
| | | } |
| | | }catch (Exception e){ |
| | | logger.error("报错日志出错了,",e); |
| | | } catch (Exception e) { |
| | | logger.error("报错日志出错了,", e); |
| | | } |
| | | } |
| | | |
| | |
| | | this.restTemplate = restTemplate; |
| | | } |
| | | |
| | | public IQueryServiceSMO getQueryServiceSMOImpl() { |
| | | return queryServiceSMOImpl; |
| | | } |
| | | |
| | | public void setQueryServiceSMOImpl(IQueryServiceSMO queryServiceSMOImpl) { |
| | | this.queryServiceSMOImpl = queryServiceSMOImpl; |
| | | } |
| | | |
| | | public RestTemplate getRestTemplateNoLoadBalanced() { |
| | | return restTemplateNoLoadBalanced; |