设计安全的Restful接口:无用户交互状态的接口安全设计。我们需要实现UR拦截请求拦截,接口接入授权验证和请求验重。本文中不涉及任何用户校验。
设计原理
1.UR拦截请求拦截:通过URL进行拦截过滤;
2.接入授权验证:验证请求头Token;
3.请求验重:验证请求序列Sequence;
接口设计文档请参考:WMS系统对外开放接口设计文档-V.1.0.docx
注:文档禁用于商业用途!
安全过滤器
- package com.wlyd.fmcgwms.util.security;
- import java.io.IOException;
- import java.io.PrintWriter;
- 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.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import com.alibaba.fastjson.JSONObject;
- import com.wlyd.fmcgwms.util.Log;
- import com.wlyd.fmcgwms.util.SAASTokenManager;
- import com.wlyd.fmcgwms.util.StaticProperty;
- import com.wlyd.fmcgwms.util.api.RSAUtils;
- import com.wlyd.fmcgwms.util.ehcache.EhcacheUtil;
- import com.wlyd.fmcgwms.util.sysinit.InitSysProperties;
- /**
- * 接口安全过滤器
- *
- * @package com.wlyd.fmcgwms.util.security.SecurityFilter
- * @date 2017年3月15日 下午1:57:18
- * @author pengjunlin
- * @comment
- * @update
- */
- public class SecurityFilter implements Filter {
- private static String API_ISENABLE ;// WMS是否开通对外接口
- private static String API_PALTFORM;// WMS开放的平台编码
- private static String API_MEMBERCODE;//WMS开放的服务商编码
- private static String publicKey;// 公钥
- private static String privateKey;// 私钥
- @Override
- public void destroy() {
- // TODO Auto-generated method stub
- }
- /**
- * 验证配置是否规范
- *
- * @MethodName: isConfiged
- * @Description:
- * @param platformCode
- * @param memberCode
- * @return
- * @throws
- */
- private boolean isConfiged(String platformCode,String memberCode){
- if(API_ISENABLE==null||!API_ISENABLE.equals("true")){
- return false;
- }
- if(API_PALTFORM==null||platformCode==null||!platformCode.equals(API_PALTFORM)){
- return false;
- }
- if (API_MEMBERCODE==null||memberCode == null||! memberCode.equals(API_MEMBERCODE)) {
- return false;
- }
- return true;
- }
- /**
- * 验证token是否有效
- *
- * @MethodName: validateToken
- * @Description:
- * @param token
- * @return
- * @throws
- */
- private boolean validateToken(String token){
- if(token==null||token.equals("")){
- return false;
- }
- String params[]=SAASTokenManager.decryptToken(privateKey, token, "&");
- if(params==null||params.length<3){
- return false;
- }
- long now=System.currentTimeMillis();
- // Token超时验证20s
- long seconds=(now-Long.valueOf(params[2]))/1000;
- if(!API_PALTFORM.equals(params[0])||!API_MEMBERCODE.equals(params[1])||seconds>20){
- return false;
- }
- return true;
- }
- /**
- * 验证请求是否重复
- *
- * @MethodName: validateSequece
- * @Description:
- * @param sequence
- * @return
- * @throws
- */
- public boolean validateSequece(String sequence){
- if(sequence==null||sequence.equals("")){
- return false;
- }
- String requestSequence=(String) EhcacheUtil.get(StaticProperty.REQUESTCACHE, sequence);
- // 请求序列相同验证失败
- if(requestSequence!=null&&sequence.equals(requestSequence)){
- return false;
- }
- return true;
- }
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- PrintWriter out = null;
- HttpServletRequest req = (HttpServletRequest) request;
- HttpServletResponse res = (HttpServletResponse) response;
- String platformCode = req.getHeader("PlatformCode");
- String memberCode = req.getHeader("MemberCode");
- String token = req.getHeader("Token");
- String sequence = req.getHeader("Sequence");
- //String path = req.getServletPath();
- try {
- byte [] bytes=SAASTokenManager.generateBytesToken(publicKey, platformCode, memberCode,"&");
- token = RSAUtils.bytesToString(bytes);
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- // 验证接口是否配置正确
- if(!isConfiged(platformCode, memberCode)){
- JSONObject json = new JSONObject();
- json.put("IsSuccess", "false");
- json.put("OperationDesc", "API parameters are not configed right! ");
- json.put("ResultCode", ResultCode.OPEN_API_CONFIG_ERROR);
- try {
- out = res.getWriter();
- out.write(json.toJSONString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- return;
- }
- // 验证Token是否合法
- if(!validateToken(token)){
- JSONObject json = new JSONObject();
- json.put("IsSuccess", "false");
- json.put("OperationDesc", "Unauthorized:Token is invalid!");
- json.put("ResultCode", ResultCode.OPEN_API_TOKEN_INVALID);
- try {
- out = res.getWriter();
- out.write(json.toJSONString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- return;
- }
- // 验证Sequence是否合法
- if(!validateSequece(sequence)){
- JSONObject json = new JSONObject();
- json.put("IsSuccess", "false");
- json.put("OperationDesc", "Refused:request API too frequently!");
- json.put("ResultCode", ResultCode.OPEN_API_REQUEST_REQUENTLY);
- try {
- out = res.getWriter();
- out.write(json.toJSONString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- return;
- }
- chain.doFilter(request, response);
- }
- @Override
- public void init(FilterConfig arg0) throws ServletException {
- Log.getLogger(getClass()).info(">>>SecurityFilter invoke init method。。。。。。。。。START!");
- API_ISENABLE = InitSysProperties.getLowerCaseFromEhcache(StaticProperty.WMS_OPEN_API_ISENABLE);
- API_PALTFORM = InitSysProperties.getUpperCaseFromEhcache(StaticProperty.WMS_OPEN_API_PLATFORM);
- API_MEMBERCODE = InitSysProperties.getUpperCaseFromEhcache(StaticProperty.WMS_OPEN_API_MEMBERCODE);
- publicKey=EhcacheUtil.get(StaticProperty.WMS_OPEN_API_RSA_PUBLIC_KEY).toString();
- privateKey=EhcacheUtil.get(StaticProperty.WMS_OPEN_API_RSA_PRIVATE_KEY).toString();
- Log.getLogger(getClass()).info(">>>SecurityFilter invoke init method。。。。。。。。。SUCCESS!");
- }
- }
package com.wlyd.fmcgwms.util.security;
import java.io.IOException;
import java.io.PrintWriter;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import com.wlyd.fmcgwms.util.Log;
import com.wlyd.fmcgwms.util.SAASTokenManager;
import com.wlyd.fmcgwms.util.StaticProperty;
import com.wlyd.fmcgwms.util.api.RSAUtils;
import com.wlyd.fmcgwms.util.ehcache.EhcacheUtil;
import com.wlyd.fmcgwms.util.sysinit.InitSysProperties;
/**
* 接口安全过滤器
*
* @package com.wlyd.fmcgwms.util.security.SecurityFilter
* @date 2017年3月15日 下午1:57:18
* @author pengjunlin
* @comment
* @update
*/
public class SecurityFilter implements Filter {
private static String API_ISENABLE ;// WMS是否开通对外接口
private static String API_PALTFORM;// WMS开放的平台编码
private static String API_MEMBERCODE;//WMS开放的服务商编码
private static String publicKey;// 公钥
private static String privateKey;// 私钥
@Override
public void destroy() {
// TODO Auto-generated method stub
}
/**
* 验证配置是否规范
*
* @MethodName: isConfiged
* @Description:
* @param platformCode
* @param memberCode
* @return
* @throws
*/
private boolean isConfiged(String platformCode,String memberCode){
if(API_ISENABLE==null||!API_ISENABLE.equals("true")){
return false;
}
if(API_PALTFORM==null||platformCode==null||!platformCode.equals(API_PALTFORM)){
return false;
}
if (API_MEMBERCODE==null||memberCode == null||! memberCode.equals(API_MEMBERCODE)) {
return false;
}
return true;
}
/**
* 验证token是否有效
*
* @MethodName: validateToken
* @Description:
* @param token
* @return
* @throws
*/
private boolean validateToken(String token){
if(token==null||token.equals("")){
return false;
}
String params[]=SAASTokenManager.decryptToken(privateKey, token, "&");
if(params==null||params.length<3){
return false;
}
long now=System.currentTimeMillis();
// Token超时验证20s
long seconds=(now-Long.valueOf(params[2]))/1000;
if(!API_PALTFORM.equals(params[0])||!API_MEMBERCODE.equals(params[1])||seconds>20){
return false;
}
return true;
}
/**
* 验证请求是否重复
*
* @MethodName: validateSequece
* @Description:
* @param sequence
* @return
* @throws
*/
public boolean validateSequece(String sequence){
if(sequence==null||sequence.equals("")){
return false;
}
String requestSequence=(String) EhcacheUtil.get(StaticProperty.REQUESTCACHE, sequence);
// 请求序列相同验证失败
if(requestSequence!=null&&sequence.equals(requestSequence)){
return false;
}
return true;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
PrintWriter out = null;
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String platformCode = req.getHeader("PlatformCode");
String memberCode = req.getHeader("MemberCode");
String token = req.getHeader("Token");
String sequence = req.getHeader("Sequence");
//String path = req.getServletPath();
try {
byte [] bytes=SAASTokenManager.generateBytesToken(publicKey, platformCode, memberCode,"&");
token = RSAUtils.bytesToString(bytes);
} catch (Exception e1) {
e1.printStackTrace();
}
// 验证接口是否配置正确
if(!isConfiged(platformCode, memberCode)){
JSONObject json = new JSONObject();
json.put("IsSuccess", "false");
json.put("OperationDesc", "API parameters are not configed right! ");
json.put("ResultCode", ResultCode.OPEN_API_CONFIG_ERROR);
try {
out = res.getWriter();
out.write(json.toJSONString());
} catch (Exception e) {
e.printStackTrace();
}
return;
}
// 验证Token是否合法
if(!validateToken(token)){
JSONObject json = new JSONObject();
json.put("IsSuccess", "false");
json.put("OperationDesc", "Unauthorized:Token is invalid!");
json.put("ResultCode", ResultCode.OPEN_API_TOKEN_INVALID);
try {
out = res.getWriter();
out.write(json.toJSONString());
} catch (Exception e) {
e.printStackTrace();
}
return;
}
// 验证Sequence是否合法
if(!validateSequece(sequence)){
JSONObject json = new JSONObject();
json.put("IsSuccess", "false");
json.put("OperationDesc", "Refused:request API too frequently!");
json.put("ResultCode", ResultCode.OPEN_API_REQUEST_REQUENTLY);
try {
out = res.getWriter();
out.write(json.toJSONString());
} catch (Exception e) {
e.printStackTrace();
}
return;
}
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
Log.getLogger(getClass()).info(">>>SecurityFilter invoke init method。。。。。。。。。START!");
API_ISENABLE = InitSysProperties.getLowerCaseFromEhcache(StaticProperty.WMS_OPEN_API_ISENABLE);
API_PALTFORM = InitSysProperties.getUpperCaseFromEhcache(StaticProperty.WMS_OPEN_API_PLATFORM);
API_MEMBERCODE = InitSysProperties.getUpperCaseFromEhcache(StaticProperty.WMS_OPEN_API_MEMBERCODE);
publicKey=EhcacheUtil.get(StaticProperty.WMS_OPEN_API_RSA_PUBLIC_KEY).toString();
privateKey=EhcacheUtil.get(StaticProperty.WMS_OPEN_API_RSA_PRIVATE_KEY).toString();
Log.getLogger(getClass()).info(">>>SecurityFilter invoke init method。。。。。。。。。SUCCESS!");
}
}
注:需要通过RSA工具生成密钥对(公钥&私钥)。
web.xml配置过滤器
- <filter>
- <filter-name>SecurityFilter</filter-name>
- <filter-class>com.wlyd.fmcgwms.util.security.SecurityFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>SecurityFilter</filter-name>
- <url-pattern>/openapi/*</url-pattern>
- </filter-mapping>
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>com.wlyd.fmcgwms.util.security.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/openapi/*</url-pattern>
</filter-mapping>
控制层openapi接口
- package com.wlyd.fmcgwms.controller.security;
- import java.util.HashMap;
- import java.util.Map;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.wlyd.fmcgwms.controller.BaseController;
- import com.wlyd.fmcgwms.util.Tools;
- /**
- * 开放API控制层
- *
- * @package com.wlyd.fmcgwms.controller.platform.OpenAPIController
- * @date 2017年3月14日 下午4:52:12
- * @author pengjunlin
- * @comment
- * @update
- */
- @Controller
- @RequestMapping("/openapi")
- public class OpenAPIController extends BaseController{
- /**
- * 未授权
- *
- * @MethodName: unauthenticated
- * @Description:
- * @return
- * @throws
- */
- @RequestMapping("/unauthenticated")
- @ResponseBody
- public String unauthenticated(){
- Map<String,Object> map=new HashMap<String, Object>();
- map.put("IsSuccess", "false");
- map.put("OperationDesc", "Unauthenticated:Please contact to WMS developers!");
- return Tools.toJson(map);
- }
- /**
- * 授权成功
- *
- * @MethodName: success
- * @Description:
- * @return
- * @throws
- */
- @RequestMapping("/success")
- @ResponseBody
- public String success(){
- Map<String,Object> map=new HashMap<String, Object>();
- map.put("IsSuccess", "true");
- map.put("OperationDesc", "Authenticated!");
- return Tools.toJson(map);
- }
- }
package com.wlyd.fmcgwms.controller.security;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.wlyd.fmcgwms.controller.BaseController;
import com.wlyd.fmcgwms.util.Tools;
/**
* 开放API控制层
*
* @package com.wlyd.fmcgwms.controller.platform.OpenAPIController
* @date 2017年3月14日 下午4:52:12
* @author pengjunlin
* @comment
* @update
*/
@Controller
@RequestMapping("/openapi")
public class OpenAPIController extends BaseController{
/**
* 未授权
*
* @MethodName: unauthenticated
* @Description:
* @return
* @throws
*/
@RequestMapping("/unauthenticated")
@ResponseBody
public String unauthenticated(){
Map<String,Object> map=new HashMap<String, Object>();
map.put("IsSuccess", "false");
map.put("OperationDesc", "Unauthenticated:Please contact to WMS developers!");
return Tools.toJson(map);
}
/**
* 授权成功
*
* @MethodName: success
* @Description:
* @return
* @throws
*/
@RequestMapping("/success")
@ResponseBody
public String success(){
Map<String,Object> map=new HashMap<String, Object>();
map.put("IsSuccess", "true");
map.put("OperationDesc", "Authenticated!");
return Tools.toJson(map);
}
}
没有其它的方法。
RSA加密工具
- package com.wlyd.fmcgwms.util.api;
- import java.io.ByteArrayOutputStream;
- import java.security.Key;
- import java.security.KeyFactory;
- import java.security.KeyPair;
- import java.security.KeyPairGenerator;
- import java.security.PrivateKey;
- import java.security.PublicKey;
- import java.security.Signature;
- import java.security.interfaces.RSAPrivateKey;
- import java.security.interfaces.RSAPublicKey;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.security.spec.X509EncodedKeySpec;
- import java.util.HashMap;
- import java.util.Map;
- import javax.crypto.Cipher;
- /**
- * <p>
- * RSA公钥/私钥/签名工具包
- * </p>
- * <p>
- * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)
- * </p>
- * <p>
- * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
- * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
- * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
- * </p>
- *
- * @author IceWee
- * @date 2012-4-26
- * @version 1.0
- */
- public class RSAUtils {
- /**
- * 加密算法RSA
- */
- public static final String KEY_ALGORITHM = "RSA";
- /**
- * 签名算法
- */
- public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
- /**
- * 获取公钥的key
- */
- private static final String PUBLIC_KEY = "RSAPublicKey";
- /**
- * 获取私钥的key
- */
- private static final String PRIVATE_KEY = "RSAPrivateKey";
- /**
- * RSA最大加密明文大小
- */
- private static final int MAX_ENCRYPT_BLOCK = 117;
- /**
- * RSA最大解密密文大小
- */
- private static final int MAX_DECRYPT_BLOCK = 128;
- /**
- * <p>
- * 生成密钥对(公钥和私钥)
- * </p>
- *
- * @return
- * @throws Exception
- */
- public static Map<String, Object> genKeyPair() throws Exception {
- KeyPairGenerator keyPairGen = KeyPairGenerator
- .getInstance(KEY_ALGORITHM);
- keyPairGen.initialize(1024);
- KeyPair keyPair = keyPairGen.generateKeyPair();
- RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
- RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
- Map<String, Object> keyMap = new HashMap<String, Object>(2);
- keyMap.put(PUBLIC_KEY, publicKey);
- keyMap.put(PRIVATE_KEY, privateKey);
- return keyMap;
- }
- /**
- * <p>
- * 用私钥对信息生成数字签名
- * </p>
- *
- * @param data
- * 已加密数据
- * @param privateKey
- * 私钥(BASE64编码)
- *
- * @return
- * @throws Exception
- */
- public static String sign(byte[] data, String privateKey) throws Exception {
- byte[] keyBytes = Base64Utils.decode(privateKey);
- PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
- Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
- signature.initSign(privateK);
- signature.update(data);
- return Base64Utils.encode(signature.sign());
- }
- /**
- * <p>
- * 校验数字签名
- * </p>
- *
- * @param data
- * 已加密数据
- * @param publicKey
- * 公钥(BASE64编码)
- * @param sign
- * 数字签名
- *
- * @return
- * @throws Exception
- *
- */
- public static boolean verify(byte[] data, String publicKey, String sign)
- throws Exception {
- byte[] keyBytes = Base64Utils.decode(publicKey);
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- PublicKey publicK = keyFactory.generatePublic(keySpec);
- Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
- signature.initVerify(publicK);
- signature.update(data);
- return signature.verify(Base64Utils.decode(sign));
- }
- /**
- * <P>
- * 私钥解密
- * </p>
- *
- * @param encryptedData
- * 已加密数据
- * @param privateKey
- * 私钥(BASE64编码)
- * @return
- * @throws Exception
- */
- public static byte[] decryptByPrivateKey(byte[] encryptedData,
- String privateKey) throws Exception {
- byte[] keyBytes = Base64Utils.decode(privateKey);
- PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
- Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
- cipher.init(Cipher.DECRYPT_MODE, privateK);
- int inputLen = encryptedData.length;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int offSet = 0;
- byte[] cache;
- int i = 0;
- // 对数据分段解密
- while (inputLen - offSet > 0) {
- if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
- cache = cipher
- .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
- } else {
- cache = cipher
- .doFinal(encryptedData, offSet, inputLen - offSet);
- }
- out.write(cache, 0, cache.length);
- i++;
- offSet = i * MAX_DECRYPT_BLOCK;
- }
- byte[] decryptedData = out.toByteArray();
- out.close();
- return decryptedData;
- }
- /**
- * <p>
- * 公钥解密
- * </p>
- *
- * @param encryptedData
- * 已加密数据
- * @param publicKey
- * 公钥(BASE64编码)
- * @return
- * @throws Exception
- */
- public static byte[] decryptByPublicKey(byte[] encryptedData,
- String publicKey) throws Exception {
- byte[] keyBytes = Base64Utils.decode(publicKey);
- X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- Key publicK = keyFactory.generatePublic(x509KeySpec);
- Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
- cipher.init(Cipher.DECRYPT_MODE, publicK);
- int inputLen = encryptedData.length;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int offSet = 0;
- byte[] cache;
- int i = 0;
- // 对数据分段解密
- while (inputLen - offSet > 0) {
- if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
- cache = cipher
- .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
- } else {
- cache = cipher
- .doFinal(encryptedData, offSet, inputLen - offSet);
- }
- out.write(cache, 0, cache.length);
- i++;
- offSet = i * MAX_DECRYPT_BLOCK;
- }
- byte[] decryptedData = out.toByteArray();
- out.close();
- return decryptedData;
- }
- /**
- * <p>
- * 公钥加密
- * </p>
- *
- * @param data
- * 源数据
- * @param publicKey
- * 公钥(BASE64编码)
- * @return
- * @throws Exception
- */
- public static byte[] encryptByPublicKey(byte[] data, String publicKey)
- throws Exception {
- byte[] keyBytes = Base64Utils.decode(publicKey);
- X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- Key publicK = keyFactory.generatePublic(x509KeySpec);
- // 对数据加密
- Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
- cipher.init(Cipher.ENCRYPT_MODE, publicK);
- int inputLen = data.length;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int offSet = 0;
- byte[] cache;
- int i = 0;
- // 对数据分段加密
- while (inputLen - offSet > 0) {
- if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
- cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
- } else {
- cache = cipher.doFinal(data, offSet, inputLen - offSet);
- }
- out.write(cache, 0, cache.length);
- i++;
- offSet = i * MAX_ENCRYPT_BLOCK;
- }
- byte[] encryptedData = out.toByteArray();
- out.close();
- return encryptedData;
- }
- /**
- * <p>
- * 私钥加密
- * </p>
- *
- * @param data
- * 源数据
- * @param privateKey
- * 私钥(BASE64编码)
- * @return
- * @throws Exception
- */
- public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
- throws Exception {
- byte[] keyBytes = Base64Utils.decode(privateKey);
- PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
- Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
- cipher.init(Cipher.ENCRYPT_MODE, privateK);
- int inputLen = data.length;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int offSet = 0;
- byte[] cache;
- int i = 0;
- // 对数据分段加密
- while (inputLen - offSet > 0) {
- if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
- cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
- } else {
- cache = cipher.doFinal(data, offSet, inputLen - offSet);
- }
- out.write(cache, 0, cache.length);
- i++;
- offSet = i * MAX_ENCRYPT_BLOCK;
- }
- byte[] encryptedData = out.toByteArray();
- out.close();
- return encryptedData;
- }
- /**
- * <p>
- * 获取私钥
- * </p>
- *
- * @param keyMap
- * 密钥对
- * @return
- * @throws Exception
- */
- public static String getPrivateKey(Map<String, Object> keyMap)
- throws Exception {
- Key key = (Key) keyMap.get(PRIVATE_KEY);
- return Base64Utils.encode(key.getEncoded());
- }
- /**
- * <p>
- * 获取公钥
- * </p>
- *
- * @param keyMap
- * 密钥对
- * @return
- * @throws Exception
- */
- public static String getPublicKey(Map<String, Object> keyMap)
- throws Exception {
- Key key = (Key) keyMap.get(PUBLIC_KEY);
- return Base64Utils.encode(key.getEncoded());
- }
- /**
- * 将加密后的字节数组转换为对象
- *
- * @MethodName: bytesToString
- * @Description:
- * @param encrytpByte
- * @return
- * @throws
- */
- public static String bytesToString(byte[] encrytpByte) {
- String result = "";
- for (Byte bytes : encrytpByte) {
- result += bytes.toString() + " ";
- }
- return result;
- }
- /**
- * 公钥加密
- *
- * @MethodName: encrypt
- * @Description:
- * @param publicKey
- * @param obj
- * @return
- * @throws
- */
- public static byte[] encrypt(RSAPublicKey publicKey, byte[] obj) {
- if (publicKey != null) {
- try {
- Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
- cipher.init(Cipher.ENCRYPT_MODE, publicKey);
- return cipher.doFinal(obj);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
- /**
- * 私钥加密
- *
- * @MethodName: decrypt
- * @Description:
- * @param privateKey
- * @param obj
- * @return
- * @throws
- */
- public static byte[] decrypt(RSAPrivateKey privateKey, byte[] obj) {
- if (privateKey != null) {
- try {
- Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- return cipher.doFinal(obj);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
- }
package com.wlyd.fmcgwms.util.api;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
/**
* <p>
* RSA公钥/私钥/签名工具包
* </p>
* <p>
* 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)
* </p>
* <p>
* 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
* 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
* 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
* </p>
*
* @author IceWee
* @date 2012-4-26
* @version 1.0
*/
public class RSAUtils {
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* 获取公钥的key
*/
private static final String PUBLIC_KEY = "RSAPublicKey";
/**
* 获取私钥的key
*/
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* <p>
* 生成密钥对(公钥和私钥)
* </p>
*
* @return
* @throws Exception
*/
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator
.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* <p>
* 用私钥对信息生成数字签名
* </p>
*
* @param data
* 已加密数据
* @param privateKey
* 私钥(BASE64编码)
*
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateK);
signature.update(data);
return Base64Utils.encode(signature.sign());
}
/**
* <p>
* 校验数字签名
* </p>
*
* @param data
* 已加密数据
* @param publicKey
* 公钥(BASE64编码)
* @param sign
* 数字签名
*
* @return
* @throws Exception
*
*/
public static boolean verify(byte[] data, String publicKey, String sign)
throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicK);
signature.update(data);
return signature.verify(Base64Utils.decode(sign));
}
/**
* <P>
* 私钥解密
* </p>
*
* @param encryptedData
* 已加密数据
* @param privateKey
* 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData,
String privateKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* <p>
* 公钥解密
* </p>
*
* @param encryptedData
* 已加密数据
* @param publicKey
* 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData,
String publicKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* <p>
* 公钥加密
* </p>
*
* @param data
* 源数据
* @param publicKey
* 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/**
* <p>
* 私钥加密
* </p>
*
* @param data
* 源数据
* @param privateKey
* 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/**
* <p>
* 获取私钥
* </p>
*
* @param keyMap
* 密钥对
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64Utils.encode(key.getEncoded());
}
/**
* <p>
* 获取公钥
* </p>
*
* @param keyMap
* 密钥对
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64Utils.encode(key.getEncoded());
}
/**
* 将加密后的字节数组转换为对象
*
* @MethodName: bytesToString
* @Description:
* @param encrytpByte
* @return
* @throws
*/
public static String bytesToString(byte[] encrytpByte) {
String result = "";
for (Byte bytes : encrytpByte) {
result += bytes.toString() + " ";
}
return result;
}
/**
* 公钥加密
*
* @MethodName: encrypt
* @Description:
* @param publicKey
* @param obj
* @return
* @throws
*/
public static byte[] encrypt(RSAPublicKey publicKey, byte[] obj) {
if (publicKey != null) {
try {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 私钥加密
*
* @MethodName: decrypt
* @Description:
* @param privateKey
* @param obj
* @return
* @throws
*/
public static byte[] decrypt(RSAPrivateKey privateKey, byte[] obj) {
if (privateKey != null) {
try {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
Token管理工具
- package com.wlyd.fmcgwms.util;
- import java.sql.Timestamp;
- import java.util.Date;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import com.wlyd.fmcgwms.persistence.beans.api.AccessToken;
- import com.wlyd.fmcgwms.util.api.Base64Utils;
- import com.wlyd.fmcgwms.util.api.RSAUtils;
- import com.wlyd.fmcgwms.util.ehcache.EhcacheUtil;
- import com.wlyd.fmcgwms.util.sysinit.InitSysProperties;
- /**
- * SAAS Token管理工具
- *
- * @packge com.wlyd.wmscloud.util.SAASTokenManager
- * @date 2016年5月6日 上午10:20:01
- * @author pengjunlin
- * @comment
- * @update
- */
- public class SAASTokenManager {
- /**
- * Token存储对象,保持100000个并发容量(K-useraccount@corCode,V-token)
- */
- private static final Map<String, Object> map = new ConcurrentHashMap<String, Object>(
- 100000);
- /**
- * 获取用户Token
- *
- * @MethodName: getToken
- * @Description:
- * @param key
- * @return
- * @throws
- */
- public static AccessToken getToken(String key) {
- if (map.containsKey(key)) {
- return (AccessToken) map.get(key);
- }
- return null;
- }
- /**
- * 添加用户token
- *
- * @MethodName: putToken
- * @Description:
- * @param key
- * useraccount@corCode
- * @param accessToken
- * @throws
- */
- public static void putToken(String key, AccessToken accessToken) {
- map.put(key, accessToken);
- }
- /**
- * 移除token
- *
- * @MethodName: removeToken
- * @Description:
- * @param key
- * useraccount@corCode
- * @throws
- */
- public static void removeToken(String key) {
- if (map.containsKey(key)) {
- map.remove(key);
- }
- }
- /**
- * 验证Token是否过期
- *
- * @MethodName: isVlidateToken
- * @Description:
- * @param key
- * useraccount@corCode
- * @return
- * @throws
- */
- public static boolean isVlidateToken(String key) {
- if (map.containsKey(key)) {
- AccessToken accessToken = (AccessToken) map.get(key);
- long currentTimestamp = new Date().getTime();
- // 有效时间两小时
- if (accessToken.getLongTime() - currentTimestamp > 2 * 3600 * 1000) {
- return false;
- }
- return true;
- }
- return false;
- }
- /**
- * 更新Token
- *
- * @MethodName: reputToken
- * @Description:
- * @param key
- * useraccount@corCode
- * @param accessToken
- * @return
- * @throws
- */
- public static void reputToken(String key, AccessToken accessToken) {
- if (map.containsKey(key)) {
- putToken(key, accessToken);
- }
- }
- /**
- * 更新Token
- *
- * @MethodName: reputToken
- * @Description:
- * @param key
- * useraccount@corCode
- * @param tokenStr
- * @return
- * @throws
- */
- public static void reputToken(String key, String tokenStr) {
- if (map.containsKey(key)) {
- AccessToken accessToken = new AccessToken();
- accessToken.setToken(tokenStr);
- accessToken.setTimestamp(new Timestamp(new Date().getTime()));
- putToken(key, accessToken);
- }
- }
- /**
- * 是否包含用户token
- * @MethodName: iscontainKey
- * @Description:
- * @param key
- * useraccount@corCode
- * @return
- * @throws
- */
- public static boolean iscontainKey(String key){
- return map.containsKey(key);
- }
- /**
- * 生成RSA加密 Token
- *
- * @MethodName: generateToken
- * @Description:
- * @param platformCode
- * @param tenantCode
- * @return
- * @throws
- */
- public static String generateToken(String publicKey,String platformCode,String tenantCode){
- String str=platformCode+"$"+tenantCode+"$"+new Date().getTime();
- try {
- byte [] bytes= RSAUtils.encryptByPublicKey(str.getBytes(),publicKey);
- // return new String( bytes ,"UTF-8");
- return Base64Utils.encode(bytes);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 生成RSA加密 Token
- *
- * @MethodName: generateBytesToken
- * @Description:
- * @param platformCode
- * @param tenantCode
- * @return
- * @throws
- */
- public static byte [] generateBytesToken(String publicKey,String platformCode,String tenantCode){
- byte [] bytes=new byte[0];
- String str=platformCode+"$"+tenantCode+"$"+new Date().getTime();
- try {
- bytes= RSAUtils.encryptByPublicKey(str.getBytes(),publicKey);
- return bytes;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 生成RSA加密 Token
- *
- * @MethodName: generateBytesToken
- * @Description:
- * @param platformCode
- * @param tenantCode
- * @param regex
- * @return
- * @throws
- */
- public static byte [] generateBytesToken(String publicKey,String platformCode,String tenantCode,String regex){
- byte [] bytes=new byte[0];
- String str=platformCode+regex+tenantCode+regex+new Date().getTime();
- try {
- bytes= RSAUtils.encryptByPublicKey(str.getBytes(),publicKey);
- return bytes;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 模拟自动生成Token
- *
- * @MethodName: getToken
- * @Description:
- * @return
- * @throws
- */
- public static String getToken(){
- // 开启线程同步库存数据到OMS
- /*Map<String, Object> keyMap=null;
- try {
- keyMap = RSAUtils.genKeyPair();
- } catch (Exception e) {
- e.printStackTrace();
- }
- String publicKey=null;
- try {
- publicKey = RSAUtils.getPublicKey(keyMap);
- } catch (Exception e) {
- e.printStackTrace();
- }
- String privateKey=null;
- try {
- privateKey = RSAUtils.getPrivateKey(keyMap);
- } catch (Exception e) {
- e.printStackTrace();
- }*/
- String token=null;
- try {
- String publicKey=EhcacheUtil.get("OMS_RSA_PUBLIC_KEY").toString();
- //String privateKey=EhcacheUtil.get("OMS_RSA_PRIVATE_KEY").toString();
- String platformCode = (String) EhcacheUtil.get("WAAS_PLATFORMCODE");
- String memberCode = InitSysProperties.getUpperCaseFromEhcache(StaticProperty.WAAS_MEMBERCODE);
- token = SAASTokenManager.generateToken(publicKey, platformCode, memberCode);
- if(token!=null){
- token.replaceAll("\\n", "");
- token.replaceAll("\\r", "");
- }
- } catch (Exception e) {
- Log.getLogger(SAASTokenManager.class).error("Token Error:"+e.getMessage());
- e.printStackTrace();
- }
- return token;
- }
- /**
- * 解密Token
- *
- * @MethodName: decryptToken
- * @Description:
- * @param privateKey
- * @param token
- * @param regex
- * @return
- * @throws
- */
- public static String [] decryptToken(String privateKey,String token,String regex){
- String params[]=new String[0];
- try {
- String[] strArr = token.split(" ");
- int len = strArr.length;
- // 转回bytes
- byte[] clone = new byte[len];
- for (int i = 0; i < len; i++) {
- clone[i] = Byte.parseByte(strArr[i]);
- }
- String decryptedToken=new String(RSAUtils.decryptByPrivateKey(clone, privateKey));
- params=decryptedToken.split(regex);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return params;
- }
- /**
- * @throws Exception
- * 测试函数入口
- *
- * @MethodName: main
- * @Description:
- * @param args
- * @throws
- */
- public static void main(String[] args) throws Exception {
- System.out.println(Md5.getMD5Str("123456"));
- String key = "wmsadmin@10000";
- AccessToken accessToken = new AccessToken();
- accessToken.setToken("token==xxjisifdihfifdds");
- accessToken.setTimestamp(new Timestamp(new Date().getTime()));
- putToken(key, accessToken);
- AccessToken accessToken2 = getToken(key);
- System.out.println("token:" + accessToken2.getToken());
- System.out.println("isValidate:" + isVlidateToken(key));
- Map<String, Object> keyMap=RSAUtils.genKeyPair();
- String publicKey=RSAUtils.getPublicKey(keyMap);
- String privateKey=RSAUtils.getPrivateKey(keyMap);
- System.out.println("publicKey:\n"+publicKey);
- System.out.println("privateKey:\n"+privateKey);
- String token=generateToken(publicKey,"1234", "10000");
- byte [] bitesToken=RSAUtils.encryptByPublicKey(("1234$10000$"+new Date().getTime()).getBytes(), publicKey);
- System.out.println("RSA Token:"+token);
- System.out.println("RSA bites Token加密:"+new String(bitesToken,"UTF-8"));
- System.out.println("RSA bites Token解密:"+new String(RSAUtils.decryptByPrivateKey(bitesToken, privateKey)));
- System.out.println("加密:"+new String(RSAUtils.encryptByPublicKey("this is data".getBytes(), publicKey),"UTF-8"));
- System.out.println("明文:"+new String(RSAUtils.decryptByPrivateKey(RSAUtils.encryptByPublicKey("this is data".getBytes(), publicKey), privateKey)));
- }
- }
package com.wlyd.fmcgwms.util;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.wlyd.fmcgwms.persistence.beans.api.AccessToken;
import com.wlyd.fmcgwms.util.api.Base64Utils;
import com.wlyd.fmcgwms.util.api.RSAUtils;
import com.wlyd.fmcgwms.util.ehcache.EhcacheUtil;
import com.wlyd.fmcgwms.util.sysinit.InitSysProperties;
/**
* SAAS Token管理工具
*
* @packge com.wlyd.wmscloud.util.SAASTokenManager
* @date 2016年5月6日 上午10:20:01
* @author pengjunlin
* @comment
* @update
*/
public class SAASTokenManager {
/**
* Token存储对象,保持100000个并发容量(K-useraccount@corCode,V-token)
*/
private static final Map<String, Object> map = new ConcurrentHashMap<String, Object>(
100000);
/**
* 获取用户Token
*
* @MethodName: getToken
* @Description:
* @param key
* @return
* @throws
*/
public static AccessToken getToken(String key) {
if (map.containsKey(key)) {
return (AccessToken) map.get(key);
}
return null;
}
/**
* 添加用户token
*
* @MethodName: putToken
* @Description:
* @param key
* useraccount@corCode
* @param accessToken
* @throws
*/
public static void putToken(String key, AccessToken accessToken) {
map.put(key, accessToken);
}
/**
* 移除token
*
* @MethodName: removeToken
* @Description:
* @param key
* useraccount@corCode
* @throws
*/
public static void removeToken(String key) {
if (map.containsKey(key)) {
map.remove(key);
}
}
/**
* 验证Token是否过期
*
* @MethodName: isVlidateToken
* @Description:
* @param key
* useraccount@corCode
* @return
* @throws
*/
public static boolean isVlidateToken(String key) {
if (map.containsKey(key)) {
AccessToken accessToken = (AccessToken) map.get(key);
long currentTimestamp = new Date().getTime();
// 有效时间两小时
if (accessToken.getLongTime() - currentTimestamp > 2 * 3600 * 1000) {
return false;
}
return true;
}
return false;
}
/**
* 更新Token
*
* @MethodName: reputToken
* @Description:
* @param key
* useraccount@corCode
* @param accessToken
* @return
* @throws
*/
public static void reputToken(String key, AccessToken accessToken) {
if (map.containsKey(key)) {
putToken(key, accessToken);
}
}
/**
* 更新Token
*
* @MethodName: reputToken
* @Description:
* @param key
* useraccount@corCode
* @param tokenStr
* @return
* @throws
*/
public static void reputToken(String key, String tokenStr) {
if (map.containsKey(key)) {
AccessToken accessToken = new AccessToken();
accessToken.setToken(tokenStr);
accessToken.setTimestamp(new Timestamp(new Date().getTime()));
putToken(key, accessToken);
}
}
/**
* 是否包含用户token
* @MethodName: iscontainKey
* @Description:
* @param key
* useraccount@corCode
* @return
* @throws
*/
public static boolean iscontainKey(String key){
return map.containsKey(key);
}
/**
* 生成RSA加密 Token
*
* @MethodName: generateToken
* @Description:
* @param platformCode
* @param tenantCode
* @return
* @throws
*/
public static String generateToken(String publicKey,String platformCode,String tenantCode){
String str=platformCode+"$"+tenantCode+"$"+new Date().getTime();
try {
byte [] bytes= RSAUtils.encryptByPublicKey(str.getBytes(),publicKey);
// return new String( bytes ,"UTF-8");
return Base64Utils.encode(bytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 生成RSA加密 Token
*
* @MethodName: generateBytesToken
* @Description:
* @param platformCode
* @param tenantCode
* @return
* @throws
*/
public static byte [] generateBytesToken(String publicKey,String platformCode,String tenantCode){
byte [] bytes=new byte[0];
String str=platformCode+"$"+tenantCode+"$"+new Date().getTime();
try {
bytes= RSAUtils.encryptByPublicKey(str.getBytes(),publicKey);
return bytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 生成RSA加密 Token
*
* @MethodName: generateBytesToken
* @Description:
* @param platformCode
* @param tenantCode
* @param regex
* @return
* @throws
*/
public static byte [] generateBytesToken(String publicKey,String platformCode,String tenantCode,String regex){
byte [] bytes=new byte[0];
String str=platformCode+regex+tenantCode+regex+new Date().getTime();
try {
bytes= RSAUtils.encryptByPublicKey(str.getBytes(),publicKey);
return bytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 模拟自动生成Token
*
* @MethodName: getToken
* @Description:
* @return
* @throws
*/
public static String getToken(){
// 开启线程同步库存数据到OMS
/*Map<String, Object> keyMap=null;
try {
keyMap = RSAUtils.genKeyPair();
} catch (Exception e) {
e.printStackTrace();
}
String publicKey=null;
try {
publicKey = RSAUtils.getPublicKey(keyMap);
} catch (Exception e) {
e.printStackTrace();
}
String privateKey=null;
try {
privateKey = RSAUtils.getPrivateKey(keyMap);
} catch (Exception e) {
e.printStackTrace();
}*/
String token=null;
try {
String publicKey=EhcacheUtil.get("OMS_RSA_PUBLIC_KEY").toString();
//String privateKey=EhcacheUtil.get("OMS_RSA_PRIVATE_KEY").toString();
String platformCode = (String) EhcacheUtil.get("WAAS_PLATFORMCODE");
String memberCode = InitSysProperties.getUpperCaseFromEhcache(StaticProperty.WAAS_MEMBERCODE);
token = SAASTokenManager.generateToken(publicKey, platformCode, memberCode);
if(token!=null){
token.replaceAll("\\n", "");
token.replaceAll("\\r", "");
}
} catch (Exception e) {
Log.getLogger(SAASTokenManager.class).error("Token Error:"+e.getMessage());
e.printStackTrace();
}
return token;
}
/**
* 解密Token
*
* @MethodName: decryptToken
* @Description:
* @param privateKey
* @param token
* @param regex
* @return
* @throws
*/
public static String [] decryptToken(String privateKey,String token,String regex){
String params[]=new String[0];
try {
String[] strArr = token.split(" ");
int len = strArr.length;
// 转回bytes
byte[] clone = new byte[len];
for (int i = 0; i < len; i++) {
clone[i] = Byte.parseByte(strArr[i]);
}
String decryptedToken=new String(RSAUtils.decryptByPrivateKey(clone, privateKey));
params=decryptedToken.split(regex);
} catch (Exception e) {
e.printStackTrace();
}
return params;
}
/**
* @throws Exception
* 测试函数入口
*
* @MethodName: main
* @Description:
* @param args
* @throws
*/
public static void main(String[] args) throws Exception {
System.out.println(Md5.getMD5Str("123456"));
String key = "wmsadmin@10000";
AccessToken accessToken = new AccessToken();
accessToken.setToken("token==xxjisifdihfifdds");
accessToken.setTimestamp(new Timestamp(new Date().getTime()));
putToken(key, accessToken);
AccessToken accessToken2 = getToken(key);
System.out.println("token:" + accessToken2.getToken());
System.out.println("isValidate:" + isVlidateToken(key));
Map<String, Object> keyMap=RSAUtils.genKeyPair();
String publicKey=RSAUtils.getPublicKey(keyMap);
String privateKey=RSAUtils.getPrivateKey(keyMap);
System.out.println("publicKey:\n"+publicKey);
System.out.println("privateKey:\n"+privateKey);
String token=generateToken(publicKey,"1234", "10000");
byte [] bitesToken=RSAUtils.encryptByPublicKey(("1234$10000$"+new Date().getTime()).getBytes(), publicKey);
System.out.println("RSA Token:"+token);
System.out.println("RSA bites Token加密:"+new String(bitesToken,"UTF-8"));
System.out.println("RSA bites Token解密:"+new String(RSAUtils.decryptByPrivateKey(bitesToken, privateKey)));
System.out.println("加密:"+new String(RSAUtils.encryptByPublicKey("this is data".getBytes(), publicKey),"UTF-8"));
System.out.println("明文:"+new String(RSAUtils.decryptByPrivateKey(RSAUtils.encryptByPublicKey("this is data".getBytes(), publicKey), privateKey)));
}
}
本文中所述的token我并没有保存下来,而是客户端每次来了都进行验证。
Ehcache缓存请求30s验重
缓存方案你也可以用Redis来做,这里因为项目使用的是Ehcache故将就之。
ehcahe配置:ehcache.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- 分布式缓存对象同步 采用RMI方式 官方还提供其他同步方式 此处略 -->
- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="ehcache.xsd"
- updateCheck="true" monitoring="autodetect"
- dynamicConfig="true">
- <!-- <diskStore path="java.io.tmpdir" /> -->
- <!--1. 指定除自身之外的网络群体中其他提供同步的主机列表,用“|”分开不同的主机 -->
- <!-- <cacheManagerPeerProviderFactory
- class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
- properties="peerDiscovery=manual,rmiUrls=//10.100.0.60:40004/metaCache" /> -->
- <!--2. 配宿主主机配置监听程序,来发现其他主机发来的同步请求 -->
- <!-- <cacheManagerPeerListenerFactory
- class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
- properties="port=40004,socketTimeoutMillis=120000" />此处默认8000端口 -->
- <!-- 默认缓存 -->
- <defaultCache
- maxElementsInMemory="10000"
- eternal="false"
- timeToIdleSeconds="1800"
- overflowToDisk="true"
- diskSpoolBufferSizeMB="30"
- maxElementsOnDisk="10000000"
- diskPersistent="false"
- diskExpiryThreadIntervalSeconds="120"
- memoryStoreEvictionPolicy="LRU">
- </defaultCache>
- <!-- 缓存 -->
- <cache name="metaCache"
- maxElementsInMemory="1000"
- eternal="false"
- timeToIdleSeconds="0"
- overflowToDisk="false"
- diskSpoolBufferSizeMB="30"
- maxElementsOnDisk="10000000"
- diskPersistent="false"
- diskExpiryThreadIntervalSeconds="120"
- memoryStoreEvictionPolicy="LRU">
- <!-- <cacheEventListenerFactory
- class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
- properties="replicateAsynchronously=true,
- replicatePuts=false,
- replicateUpdates=true,
- replicateUpdatesViaCopy=true,
- replicateRemovals=true "/>
- <bootstrapCacheLoaderFactory
- class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
- properties="bootstrapAsynchronously=false" /> -->
- </cache>
- <cache name="REQUESTCACHE"
- maxElementsInMemory="100000"
- eternal="false"
- timeToIdleSeconds="30"
- timeToLiveSeconds="30"
- overflowToDisk="false"
- maxElementsOnDisk="0"
- diskPersistent="false"
- diskExpiryThreadIntervalSeconds="0"
- memoryStoreEvictionPolicy="LRU">
- </cache>
- </ehcache>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 分布式缓存对象同步 采用RMI方式 官方还提供其他同步方式 此处略 -->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true" monitoring="autodetect"
dynamicConfig="true">
<!-- <diskStore path="java.io.tmpdir" /> -->
<!--1. 指定除自身之外的网络群体中其他提供同步的主机列表,用“|”分开不同的主机 -->
<!-- <cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,rmiUrls=//10.100.0.60:40004/metaCache" /> -->
<!--2. 配宿主主机配置监听程序,来发现其他主机发来的同步请求 -->
<!-- <cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="port=40004,socketTimeoutMillis=120000" />此处默认8000端口 -->
<!-- 默认缓存 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="1800"
overflowToDisk="true"
diskSpoolBufferSizeMB="30"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
<!-- 缓存 -->
<cache name="metaCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="0"
overflowToDisk="false"
diskSpoolBufferSizeMB="30"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<!-- <cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true,
replicatePuts=false,
replicateUpdates=true,
replicateUpdatesViaCopy=true,
replicateRemovals=true "/>
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
properties="bootstrapAsynchronously=false" /> -->
</cache>
<cache name="REQUESTCACHE"
maxElementsInMemory="100000"
eternal="false"
timeToIdleSeconds="30"
timeToLiveSeconds="30"
overflowToDisk="false"
maxElementsOnDisk="0"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="0"
memoryStoreEvictionPolicy="LRU">
</cache>
</ehcache>
Ehcache工具类:
- package com.wlyd.fmcgwms.util.ehcache;
- import net.sf.ehcache.Cache;
- import net.sf.ehcache.CacheManager;
- import net.sf.ehcache.Element;
- /**
- * ehcache 缓存工具类
- *
- * @packge com.wlyd.fmcgwms.util.ehcache.EhcacheUtil
- * @date 2016年4月28日 下午4:11:27
- * @author pengjunlin
- * @comment cacheName在ehcache.xml中配置
- * @update 添加注释,代码重构删除原有类com。wlyd.fmcgwms.util.ehcache.EhcacheUtilOverWrite
- */
- public class EhcacheUtil {
- public static CacheManager manager = CacheManager.create();// 缓存管理
- public static String cacheName = "metaCache";// 缓存名称
- /**
- * 获取缓存对象
- *
- * @MethodName: get
- * @Description:
- * @param key
- * @return
- * @throws
- */
- public static Object get(Object key) {
- Cache cache = manager.getCache(cacheName);
- if (cache != null) {
- Element element = cache.get(key);
- if (element != null) {
- return element.getObjectValue();
- }
- }
- return null;
- }
- /**
- * 获取缓存对象
- *
- * @MethodName: get
- * @Description:
- * @param cacheName
- * @param key
- * @return
- * @throws
- */
- public static Object get(String cacheName, Object key) {
- Cache cache = manager.getCache(cacheName);
- if (cache != null) {
- Element element = cache.get(key);
- if (element != null) {
- return element.getObjectValue();
- }
- }
- return null;
- }
- /**
- * 添加缓存对象
- *
- * @MethodName: put
- * @Description:
- * @param key
- * @param value
- * @throws
- */
- public static void put(Object key, Object value) {
- Cache cache = manager.getCache(cacheName);
- if (cache != null) {
- cache.put(new Element(key, value));
- }
- }
- /**
- * 添加缓存对象
- *
- * @MethodName: put
- * @Description:
- * @param cacheName
- * @param key
- * @param value
- * @throws
- */
- public static void put(String cacheName, Object key, Object value) {
- Cache cache = manager.getCache(cacheName);
- if (cache != null) {
- cache.put(new Element(key, value));
- }
- }
- /**
- * 移出缓存对象
- *
- * @MethodName: remove
- * @Description:
- * @param key
- * @return
- * @throws
- */
- public static boolean remove(Object key) {
- Cache cache = manager.getCache(cacheName);
- if (cache != null) {
- return cache.remove(key);
- }
- return false;
- }
- /**
- * 移除缓存对象
- *
- * @MethodName: remove
- * @Description:
- * @param cacheName
- * @param key
- * @return
- * @throws
- */
- public static boolean remove(String cacheName, Object key) {
- Cache cache = manager.getCache(cacheName);
- if (cache != null) {
- return cache.remove(key);
- }
- return false;
- }
- }
package com.wlyd.fmcgwms.util.ehcache;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
/**
* ehcache 缓存工具类
*
* @packge com.wlyd.fmcgwms.util.ehcache.EhcacheUtil
* @date 2016年4月28日 下午4:11:27
* @author pengjunlin
* @comment cacheName在ehcache.xml中配置
* @update 添加注释,代码重构删除原有类com。wlyd.fmcgwms.util.ehcache.EhcacheUtilOverWrite
*/
public class EhcacheUtil {
public static CacheManager manager = CacheManager.create();// 缓存管理
public static String cacheName = "metaCache";// 缓存名称
/**
* 获取缓存对象
*
* @MethodName: get
* @Description:
* @param key
* @return
* @throws
*/
public static Object get(Object key) {
Cache cache = manager.getCache(cacheName);
if (cache != null) {
Element element = cache.get(key);
if (element != null) {
return element.getObjectValue();
}
}
return null;
}
/**
* 获取缓存对象
*
* @MethodName: get
* @Description:
* @param cacheName
* @param key
* @return
* @throws
*/
public static Object get(String cacheName, Object key) {
Cache cache = manager.getCache(cacheName);
if (cache != null) {
Element element = cache.get(key);
if (element != null) {
return element.getObjectValue();
}
}
return null;
}
/**
* 添加缓存对象
*
* @MethodName: put
* @Description:
* @param key
* @param value
* @throws
*/
public static void put(Object key, Object value) {
Cache cache = manager.getCache(cacheName);
if (cache != null) {
cache.put(new Element(key, value));
}
}
/**
* 添加缓存对象
*
* @MethodName: put
* @Description:
* @param cacheName
* @param key
* @param value
* @throws
*/
public static void put(String cacheName, Object key, Object value) {
Cache cache = manager.getCache(cacheName);
if (cache != null) {
cache.put(new Element(key, value));
}
}
/**
* 移出缓存对象
*
* @MethodName: remove
* @Description:
* @param key
* @return
* @throws
*/
public static boolean remove(Object key) {
Cache cache = manager.getCache(cacheName);
if (cache != null) {
return cache.remove(key);
}
return false;
}
/**
* 移除缓存对象
*
* @MethodName: remove
* @Description:
* @param cacheName
* @param key
* @return
* @throws
*/
public static boolean remove(String cacheName, Object key) {
Cache cache = manager.getCache(cacheName);
if (cache != null) {
return cache.remove(key);
}
return false;
}
}
测试方法:
- package fmcgwms;
- import org.apache.http.client.methods.HttpGet;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import com.alibaba.fastjson.JSONObject;
- import com.wlyd.fmcgwms.util.Md5;
- import com.wlyd.fmcgwms.util.SAASTokenManager;
- import com.wlyd.fmcgwms.util.StaticProperty;
- import com.wlyd.fmcgwms.util.api.APIHttpClient;
- import com.wlyd.fmcgwms.util.api.RSAUtils;
- import com.wlyd.fmcgwms.util.ehcache.EhcacheUtil;
- /**
- * 开放接口对外模拟测试
- * @package fmcgwms.OpenApiTest
- * @date 2017年3月15日 下午5:51:03
- * @author pengjunlin
- * @comment
- * @update
- */
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(locations = "classpath:applicationContext.xml")
- public class OpenApiTest {
package fmcgwms;
import org.apache.http.client.methods.HttpGet;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.alibaba.fastjson.JSONObject;
import com.wlyd.fmcgwms.util.Md5;
import com.wlyd.fmcgwms.util.SAASTokenManager;
import com.wlyd.fmcgwms.util.StaticProperty;
import com.wlyd.fmcgwms.util.api.APIHttpClient;
import com.wlyd.fmcgwms.util.api.RSAUtils;
import com.wlyd.fmcgwms.util.ehcache.EhcacheUtil;
/**
* 开放接口对外模拟测试
* @package fmcgwms.OpenApiTest
* @date 2017年3月15日 下午5:51:03
* @author pengjunlin
* @comment
* @update
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class OpenApiTest {
- @Test
- ublic void testEchcacheToTimeout(){
- String requestSequence=Md5.getMD5Str("localhost&interface&opt_type&uniquecode");
- System.out.println(">>>>>原始MD5串:"+requestSequence);
- EhcacheUtil.put(StaticProperty.REQUESTCACHE, requestSequence, requestSequence);
- System.out.println(">>>>>缓存:"+EhcacheUtil.get(StaticProperty.REQUESTCACHE, requestSequence));
- try {
- Thread.sleep(31000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(">>>>>30s后缓存:"+EhcacheUtil.get(StaticProperty.REQUESTCACHE, requestSequence));
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
@Test
public void testEchcacheToTimeout(){
String requestSequence=Md5.getMD5Str("localhost&interface&opt_type&uniquecode");
System.out.println(">>>>>原始MD5串:"+requestSequence);
EhcacheUtil.put(StaticProperty.REQUESTCACHE, requestSequence, requestSequence);
System.out.println(">>>>>缓存:"+EhcacheUtil.get(StaticProperty.REQUESTCACHE, requestSequence));
try {
Thread.sleep(31000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(">>>>>30s后缓存:"+EhcacheUtil.get(StaticProperty.REQUESTCACHE, requestSequence));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Ehcache的输出:
- >>>>>原始MD5串:cae76d65fc5c47875730ed35a262abb4
- >>>>>缓存:cae76d65fc5c47875730ed35a262abb4
- 2017-03-16 15:13:49,647 [net.sf.ehcache.CacheManager@2f1a74d1] INFO [net.sf.ehcache.util.UpdateChecker] - This is the latest GA release.
- 2017-03-16 15:14:00,016 [SpringJobSchedulerFactoryBean_Worker-1] ERROR [com.wlyd.fmcgwms.persistence.beans.platform.job.CycleFetchInterfaceInfoTaskJob] - >>>WMS-WAAS接口定时任务<<启动失败---fetch----:请设置WAAS_API_ISENABLE=true
- 2017-03-16 15:14:00,016 [SpringJobSchedulerFactoryBean_Worker-2] ERROR [com.wlyd.fmcgwms.persistence.beans.platform.job.CycleSendInterfaceInfoTaskJob] - >>>WMS-WAAS定时任务<<启动失败----send---:请设置WAAS_API_ISENABLE=true
- >>>>>30s后缓存:null
>>>>>原始MD5串:cae76d65fc5c47875730ed35a262abb4
>>>>>缓存:cae76d65fc5c47875730ed35a262abb4
2017-03-16 15:13:49,647 [net.sf.ehcache.CacheManager@2f1a74d1] INFO [net.sf.ehcache.util.UpdateChecker] - This is the latest GA release.
2017-03-16 15:14:00,016 [SpringJobSchedulerFactoryBean_Worker-1] ERROR [com.wlyd.fmcgwms.persistence.beans.platform.job.CycleFetchInterfaceInfoTaskJob] - >>>WMS-WAAS接口定时任务<<启动失败---fetch----:请设置WAAS_API_ISENABLE=true
2017-03-16 15:14:00,016 [SpringJobSchedulerFactoryBean_Worker-2] ERROR [com.wlyd.fmcgwms.persistence.beans.platform.job.CycleSendInterfaceInfoTaskJob] - >>>WMS-WAAS定时任务<<启动失败----send---:请设置WAAS_API_ISENABLE=true
>>>>>30s后缓存:null
转载自:http://blog.csdn.net/boonya/article/details/62423737