• 【Java】 WebService 校验机制


    测试环境域名

    不可见

    正式环境域名

    不可见

    1.2、安全校验凭证

    accessId(授权ID

    测试/正式待定

    securityKey(加密密钥)

    测试/正式待定

    1.3、安全校验机制

    1.3.1、在请求头中必须带入的参数

    字段

    类型

    是否必填

    入参类型

    说明

    accessId

    String

    header

    dms提供

    timestamp

    Long

    header

    时间戳,精确到毫秒级

    sign

    String

    header

    算法规则见下说明

    1.3.2、安全码(sign)生成规则

    securityKey+ timestamp +method+uri+参数json字符串(入参使用TreeMap,保证两边参数排序的一致性),使用md5加密;

    注释分析代码:

    // 校验方法
    ElemBean validBean = intfAuth.isValid(request, params, true);
    
    /**
    * 必要信息:accessId
    * @param request
    * @param datas
    * @param checkSign
    * @return
    */
    public ElemBean isValid(HttpServletRequest request, Map<String, Object> datas, boolean checkSign) {
    	// 创建一个空ElemBean
    	ElemBean ret = new ElemBean();
    
    	// 先放了成功的状态
    	ret.put("stateCode", IntfAuthCode2.SUC.getStateCode());
    	ret.put("message", IntfAuthCode2.SUC.getMessage());
    	
    	// 这个是对请求进行了判空处理
    	ElemBean checkNullBean = checkCruxInfoNull(request, checkSign);
    	if(!checkNullBean.eq("stateCode", IntfAuthCode2.SUC.getStateCode())) {
    		// 空了就返回判空的处理结果
    		ret.putAll(checkNullBean);
    		return ret;
    	}
    
    	// 获取安全密钥
    	String securityKey = getSecurityKey(request.getHeader("accessId"));
    	// 密钥判空处理
    	if(securityKey == null || "".equals(securityKey)) {
    		ret.put("stateCode", IntfAuthCode2.ACCESS_ID_INVALID.getStateCode());
    		ret.put("message", IntfAuthCode2.ACCESS_ID_INVALID.getMessage());
    		return ret;
    	}
    	// 这个判断应该是一个开关,如果false就不做Sign安全码验证
    	if(checkSign) {
    		// 开始生成安全码
    		try {
    			String sign = sign(request, datas, securityKey);
    			
    			// 如果我们生成的MD5 和对方提供的不一致,返回非法访问
    			if(!sign.equals(request.getHeader("sign"))) {
    				ret.put("stateCode", IntfAuthCode2.SIGN_INVALID.getStateCode());
    				ret.put("message", IntfAuthCode2.SIGN_INVALID.getMessage());
    				return ret;
    			}
    		} catch (JsonProcessingException e) {
    			logger.error(e.getMessage(), e);
    			ret.put("stateCode", IntfAuthCode2.SIGN_INVALID.getStateCode());
    			ret.put("message", IntfAuthCode2.SIGN_INVALID.getMessage());
    		}
    	}
    	return ret;
    }
    
    // 判空方法
    ElemBean checkNullBean = checkCruxInfoNull(request, checkSign);
    
    private ElemBean checkCruxInfoNull(HttpServletRequest request, boolean checkSign) {
    	ElemBean ret = new ElemBean();
    	
    	try{
    		// 先拿出来 accessId
    		String accessId = request.getHeader("accessId");
    		
    		// 判空 accessId 空就重设状态,表示没有accessId
    		if(accessId == null || "".equals(accessId)) {
    			ret.put("stateCode", IntfAuthCode2.NO_ACCESS_ID.getStateCode());
    			ret.put("message", IntfAuthCode2.NO_ACCESS_ID.getMessage());
    			return ret; // 这里都是直接返回结束
    		}
    		// 判空 sign 空就重设状态,表示没有sign
    		if(checkSign && request.getHeader("sign") == null) {
    			ret.put("stateCode", IntfAuthCode2.NO_SIGN.getStateCode());
    			ret.put("message", IntfAuthCode2.NO_SIGN.getMessage());
    			return ret; // 这里都是直接返回结束
    		}
    		// accessId 和 sign 都有的,就返回成功
    		ret.put("stateCode", IntfAuthCode2.SUC.getStateCode());
    		ret.put("message", IntfAuthCode2.SUC.getMessage());
    	} catch(Exception e){
    		// 异常就返回  系统异常
    		ret.put("stateCode", IntfAuthCode2.SYS_ERR.getStateCode());
    		ret.put("message", IntfAuthCode2.SYS_ERR.getMessage());
    		logger.error(e.getMessage(), e);
    	}
    	
    	return ret;
    }
    
    // 获取安全密钥
    String securityKey = getSecurityKey(request.getHeader("accessId"));
    private String getSecurityKey(String accessId) {
    	String securityKey = null;
    	try{
    		// 这里访问了 dcs.interface 库
    		bt.beginTxn(IntfConstans.TXN_INTF, IntfConstans.JNDI_INTF);
    		
    		// 拿accessId(APP_ID) 找CLEINT_ID 然后返回
    		TmIntfAuthSecurityPO po = TmIntfAuthSecurityPO.findFirst("APP_ID=? AND VALID_STATUS=10011001", accessId);
    		if(po != null) {
    			securityKey = po.getString("CLEINT_ID");
    		}
    		
    		bt.endTxnTrue();
    	} catch(Exception e){
    		bt.endTxnFalse();
    		logger.error(e.getMessage(), e);
    	} finally{
    		bt.txnClean();
    	}
    	
    	return securityKey;
    }
    
    // 安全码生成规则
    String sign = sign(request, datas, securityKey);
    
    /**
    * 1、这里要提供 请求头,所以带了 HttpServletRequest
    * 2、请求的参数在 datas (requestParam)
    * 3、从dcs.interface.tm_intf_auth_security 查询的对应的CLEINT_ID(安全密钥)
    */
    public String sign(HttpServletRequest request, Map<String, Object> datas, String securityKey) throws JsonProcessingException {
    	TreeMap<String, Object> treeMap = new TreeMap<String, Object>();
    	treeMap.putAll(datas);
    	
    	// 先拿了头的时间戳
    	String timestamp = request.getHeader("timestamp");
    	
    	ObjectMapper mapper = new ObjectMapper();
    	StringBuilder signSb = new StringBuilder();
    	// 安全码(sign)生成规则 securityKey+ timestamp +method+uri+参数json字符串(入参使用TreeMap,保证两边参数排序的一致性),使用md5加密;
     
    	signSb.append(securityKey).append(timestamp.toString()).append(request.getMethod()).append(request.getRequestURI()).append(mapper.writeValueAsString(treeMap));
    	
    	// 输出显示看下
    	logger.info(timestamp+","+signSb.toString());
    	// 用MD5生成加密码
    	String sign = DigestUtils.md5Hex(signSb.toString());
    	logger.info("sign:"+sign);
    	// 返回
    	return sign;
    }
    

     

    校验源码:

    package com.yonyou.dcs.intf.common;
    
    import java.util.Map;
    import java.util.TreeMap;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.codec.digest.DigestUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.yonyou.dcs.common.bean.ElemBean;
    import com.yonyou.dcs.intf.po.TmIntfAuthSecurityPO;
    
    /**
     * 新的接口安全校验机制
     * 现用于:新车商城接口
     * @author Administrator
     *
     */
    @Service
    public class IntfAuthValid2 {
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
        @Autowired
        private BaseTxn bt;
    
        /**
         * 必要信息:accessId
         * @param request
         * @param datas
         * @param checkSign
         * @return
         */
        public ElemBean isValid(HttpServletRequest request, Map<String, Object> datas, boolean checkSign) {
            ElemBean ret = new ElemBean();
            ret.put("stateCode", IntfAuthCode2.SUC.getStateCode());
            ret.put("message", IntfAuthCode2.SUC.getMessage());
            
            ElemBean checkNullBean = checkCruxInfoNull(request, checkSign);
            if(!checkNullBean.eq("stateCode", IntfAuthCode2.SUC.getStateCode())) {
                ret.putAll(checkNullBean);
                return ret;
            }
            String securityKey = getSecurityKey(request.getHeader("accessId"));
            if(securityKey == null || "".equals(securityKey)) {
                ret.put("stateCode", IntfAuthCode2.ACCESS_ID_INVALID.getStateCode());
                ret.put("message", IntfAuthCode2.ACCESS_ID_INVALID.getMessage());
                return ret;
            }
            if(checkSign) {
                try {
                    String sign = sign(request, datas, securityKey);
                    
                    if(!sign.equals(request.getHeader("sign"))) {
                        ret.put("stateCode", IntfAuthCode2.SIGN_INVALID.getStateCode());
                        ret.put("message", IntfAuthCode2.SIGN_INVALID.getMessage());
                        return ret;
                    }
                } catch (JsonProcessingException e) {
                    logger.error(e.getMessage(), e);
                    ret.put("stateCode", IntfAuthCode2.SIGN_INVALID.getStateCode());
                    ret.put("message", IntfAuthCode2.SIGN_INVALID.getMessage());
                }
            }
            return ret;
        }
        
        public String sign(HttpServletRequest request, Map<String, Object> datas, String securityKey) throws JsonProcessingException {
            TreeMap<String, Object> treeMap = new TreeMap<String, Object>();
            treeMap.putAll(datas);
    
            String timestamp = request.getHeader("timestamp");
            
            ObjectMapper mapper = new ObjectMapper();
            StringBuilder signSb = new StringBuilder();
            signSb.append(securityKey).append(timestamp.toString()).append(request.getMethod()).append(request.getRequestURI()).append(mapper.writeValueAsString(treeMap));
            
            logger.info(timestamp+","+signSb.toString());
            
            String sign = DigestUtils.md5Hex(signSb.toString());
            logger.info("sign:"+sign);
            return sign;
        }
        
        private ElemBean checkCruxInfoNull(HttpServletRequest request, boolean checkSign) {
            ElemBean ret = new ElemBean();
            
            try{
                String accessId = request.getHeader("accessId");
                
                if(accessId == null || "".equals(accessId)) {
                    ret.put("stateCode", IntfAuthCode2.NO_ACCESS_ID.getStateCode());
                    ret.put("message", IntfAuthCode2.NO_ACCESS_ID.getMessage());
                    return ret;
                }
                if(checkSign && request.getHeader("sign") == null) {
                    ret.put("stateCode", IntfAuthCode2.NO_SIGN.getStateCode());
                    ret.put("message", IntfAuthCode2.NO_SIGN.getMessage());
                    return ret;
                }
                
                ret.put("stateCode", IntfAuthCode2.SUC.getStateCode());
                ret.put("message", IntfAuthCode2.SUC.getMessage());
            } catch(Exception e){
                ret.put("stateCode", IntfAuthCode2.SYS_ERR.getStateCode());
                ret.put("message", IntfAuthCode2.SYS_ERR.getMessage());
                logger.error(e.getMessage(), e);
            }
            
            return ret;
        }
        
        private String getSecurityKey(String accessId) {
            String securityKey = null;
            try{
                bt.beginTxn(IntfConstans.TXN_INTF, IntfConstans.JNDI_INTF);
                
                TmIntfAuthSecurityPO po = TmIntfAuthSecurityPO.findFirst("APP_ID=? AND VALID_STATUS=10011001", accessId);
                if(po != null) {
                    securityKey = po.getString("CLEINT_ID");
                }
                
                bt.endTxnTrue();
            } catch(Exception e){
                bt.endTxnFalse();
                logger.error(e.getMessage(), e);
            } finally{
                bt.txnClean();
            }
            
            return securityKey;
        }
    }

    相关的状态字典:

    1.4、返回码描述

    1.4.1、系统相关

    返回码

    描述

    0

    成功

    1.00.000

    system error,系统错误,联系管理员

    1.00.001

    no access id

    1.00.002

    access id invalid

    1.00.003

    no sign

    1.00.004

    sign invalid

    1.00.005

    数据重复接收

    1.4.2、新车商城相关

    返回码

    描述

    1.01.001

    vin信息无效

    1.01.002

    车辆未实销

    1.01.003

    车辆非江铃车

    1.01.004

    车辆行驶里程小于进厂里程

    1.01.005

    关键字段不能为空

    1.01.006

    关键字段值不正确

    1.01.007

    车辆不符合产品规则

    1.01.008

    车辆已购买过服务包

    1.01.009

    维修站无效

    1.02.001

    字段值不符合要求

    1.02.002

    商城订单号重复

    1.02.003

    商品代码不存在

      

  • 相关阅读:
    Spring参数解析器HandlerMethodArgumentResolver
    Spring拦截器HandlerInterceptor和HandlerInterceptorAdapter
    3,turicreate入门
    2,turicreate入门
    flink 配置
    maven打包,带依赖jar
    python缓存所在目录
    docker基础
    yum安装
    python3 flink 安装
  • 原文地址:https://www.cnblogs.com/mindzone/p/15078436.html
Copyright © 2020-2023  润新知