测试环境域名

不可见

正式环境域名

不可见

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

商品代码不存在

  

【Java】 WebService 校验机制的更多相关文章

  1. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  2. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  3. WebService安全机制的思考与实践

    近来因业务需要,需要研究webservice,于是便有这篇文章:SpringBoot整合Apache-CXF实践 一.WebService是什么? WebService是一个平台独立的.低耦合的.自包 ...

  4. Atitit webservice发现机制 WS-Discovery标准的规范attilax总结

    Atitit webservice发现机制 WS-Discovery标准的规范attilax总结 1.1. WS-Discovery标准1 1.2. 一.WS-Discovery1 1.2.1.   ...

  5. 深入研究Java类装载机制

    目录 1.为什么要研究java类装在机制? 2.了解类装载机制,对于我们在项目开发中有什么作用? 3.装载实现细节. 4.总结 一.为什么药研究Java类装载机制 java类加载机制,便于我们使用自定 ...

  6. java 的SPI机制

    今天看到spring mvc 使用Java Validation Api(JSR-303)进行校验,需要加载一个 其具体实现(比如Hibernate Validator), 本来没有什么问题,但是突然 ...

  7. JAVA 初识类加载机制 第13节

    JAVA 初识类加载机制 第13节 从这章开始,我们就进入虚拟机类加载机制的学习了.那么什么是类加载呢?当我们写完一个Java类的时候,并不是直接就可以运行的,它还要编译成.class文件,再由虚拟机 ...

  8. Struts2请求参数合法性校验机制

    在Action中通过代码执行数据校验 请求参数的输入校验途径一般分两种:客户端校验 :通过JavaScript 完成 (jquery validation插件),目的:过滤正常用户的误操作. 服务器校 ...

  9. Java语言实现机制

    Java语言实现机制 1.Java虚拟机(Java Virtual Machine) Java虚拟机(JVM)是在一台计算机上由软件模拟也可以用硬件来实现的假想的计算机.它定义了指令集(相当于中央处理 ...

  10. Java WebService接口生成和调用 图文详解>【转】【待调整】

    webservice简介: Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的.专门的第三方软件或硬件, 就可相互交换数据或集成.依据Web Service规范实施的应用之间 ...

随机推荐

  1. Centos7无法ping通内网、外网

    主要检查网络的配置是否正确,我测试时使用的是VMware虚拟机,需要保证centos中的网络配置和VMware中的一致. (1)VMware的配置 网络适配器选择NAT模式 查看NAT设置,这里需要记 ...

  2. Java中对的创建与引用

    对象与引用 Java语言中除了基本数据类型以外都属于引用类型 Java中的对象是通过引用对其操作的 class Car{ String name; String color; int price; } ...

  3. CF437E The Child and Polygon

    The Child and Polygon 题解 这世界这么大,遇到了这个奇奇怪怪的题. 这道题其实可以很自然的联想到卡特兰数. 在卡特兰数的计数中,有这么一个意义:\(C_n\) 表示把有 \(n+ ...

  4. MYSQL 连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,错误信息:未将对象引用设置到对象的实例。

    一: 中文提示 : 连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,错误信息:未将对象引用设置到对象的实例.DbType="MySql";ConfigId=&quo ...

  5. P2467 [SDOI2010] 地精部落 学习笔记

    DP 显然我固定第一个是峰,然后再乘以2就是答案,因为一个合法的反转之后也是合法的而且谷峰颠倒了 发现如果设\(dp[i][j]\)表示前\(i\)个山脉,第\(i\)个山脉是高度\(j\)的答案,然 ...

  6. Android7.0 配置JACK支持多用户同时编译

    # Android7.0 配置JACK支持多用户同时编译 reference: https://blog.csdn.net/whorus1/article/details/80364772 https ...

  7. SpringBoot 2.5.5整合SpringSecurity+JWT

    目录结构 添加依赖 <!-- SpringSecurity --> <dependency> <groupId>org.springframework.boot&l ...

  8. PLSQL 无法查询带中文的WHERE条件

    今天遇到一个坑爹的问题,plsql无法查询带where条件的语句,是因为plsql中Oracle的客户端字符集和服务器上的不一样造成的,需要新增系统环境变量,特意记录下解决办法. 第一步:查询服务器上 ...

  9. yb课堂之实战登陆模块开发整合Json Web Token《十》

    开发登陆模块功能,并整合Json Web Token 开发登陆功能 LoginRequest.java UserMapper.xml  UserMapper.java UserService.java ...

  10. 算法金 | 秒懂 AI - 深度学习五大模型:RNN、CNN、Transformer、BERT、GPT 简介

    1. RNN(Recurrent Neural Network) 时间轴 1986年,RNN 模型首次由 David Rumelhart 等人提出,旨在处理序列数据. 关键技术 循环结构 序列处理 长 ...