您的位置:首页 > 编程语言 > Java开发

Spring设计安全的Restful接口

2017-08-28 11:29 405 查看
设计安全的Restful接口:无用户交互状态的接口安全设计。我们需要实现UR拦截请求拦截,接口接入授权验证和请求验重。本文中不涉及任何用户校验。

设计原理

1.UR拦截请求拦截:通过URL进行拦截过滤;

2.接入授权验证:验证请求头Token;

3.请求验重:验证请求序列Sequence;

接口设计文档请参考:WMS系统对外开放接口设计文档-V.1.0.docx

注:文档禁用于商业用途!

安全过滤器

[java]
view plain
copyprint?

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&nb
1d25b
sp;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配置过滤器

[html]
view plain
copyprint?

<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接口

[java]
view plain
copyprint?

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加密工具

[java]
view plain
copyprint?

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.getEnc
2c1de
oded());
}

/**
* <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管理工具

[java]
view plain
copyprint?

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

[html]
view plain
copyprint?

<?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工具类:

[java]
view plain
copyprint?

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;
}
}


测试方法:

[java]
view plain
copyprint?

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 {


[java]
view plain
copyprint?

@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的输出:

[plain]
view plain
copyprint?

>>>>>原始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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring restful