weaver-hrm-salary/src/com/engine/salary/util/SalaryTokenUtil.java

259 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.engine.salary.util;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.engine.salary.encrypt.AESEncryptUtil;
import com.engine.salary.entity.salaryBill.param.SalaryBillGetTokenParam;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.util.db.IdGenerator;
import org.apache.commons.lang3.StringUtils;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.rsa.security.RSA;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
public class SalaryTokenUtil {
/**
* 通过注册返回的OA系统公钥和秘钥获取token
*
* @param address OA地址
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
// public static Map<String, Object> testGetoken(String address) throws NoSuchAlgorithmException, KeyManagementException {
// Map<String, String> heads = new HashMap<>();
// Map<String, Object> datas = testRegist(address); // 注册接口返回的secrit私钥和spk公钥可以在第一次调用后第三方系统保存起来之后调用可以不用再调用这个注册接口
// //ECOLOGY返回的系统公钥
// String spk = (String) (datas.get("spk"));
// RSA rsa = new RSA();
// //对秘钥进行加密传输,防止篡改数据
// String secret = rsa.encrypt(null, (String) (datas.get("secrit")), null, "utf-8", spk, false);
// //封装参数到请求头
// heads.put("appid", APPID);
// heads.put("secret", secret);
// //调用ECOLOGY系统接口进行注册
// String data = post(address + "/api/ec/dev/auth/applytoken", null, heads);
// System.out.println("=====testGetoken=====" + data);
// return JSONObject.parseObject(data, new TypeReference<Map<String, Object>>() {
// });
// }
/**
* 注册第三方系统到OA系统第一次用APPID获取到公钥spk和私钥secret第三方系统可以保存下次不用在请求注册接口
*
* @param address OA地址
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
// public static Map<String, Object> testRegist(String address) throws NoSuchAlgorithmException, KeyManagementException {
// Map<String, String> heads = new HashMap<>();
// //获取当前异构系统RSA加密的公钥
// String cpk = new RSA().getRSA_PUB();
// //封装参数到请求头
// heads.put("appid", APPID);
// heads.put("cpk", cpk);
// //调用ECOLOGY系统接口进行注册
// String data = post(address + "/api/ec/dev/auth/regist", null, heads);
// System.out.println("=====testRegist=====" + data);
// return JSONObject.parseObject(data, new TypeReference<Map<String, Object>>() {
// });
// }
/**
* 第一次获取Token需要先注册
*
* @return
*/
public static Map<String, String> GetToken(SalaryBillGetTokenParam param) {
String uid = "";
if (StringUtils.isNotBlank(param.getSalaryCode())) {
uid = AESEncryptUtil.decrypt4SalaryBill(param.getSalaryCode());
} else {
uid = param.getRecipient();
}
Map<String, String> heads = new HashMap<>();
if (StringUtils.isBlank(uid)) {
return heads;
}
BaseBean baseBean = new BaseBean();
// 获取是否是https
String isHttps = baseBean.getPropValue("hrmSalaryBillToken", "is_https");
String httpKey = (StringUtils.isNotBlank(isHttps) && isHttps.equals("true")) ? "https://" : "http://";
RecordSet rs = new RecordSet();
Map<String, String> resultMap = new HashMap<>();
// 获取appid的id
String appidId = baseBean.getPropValue("hrmSalaryBillToken", "appid_id");
if (StringUtils.isBlank(appidId)) {
return resultMap;
}
String ip = baseBean.getPropValue("hrmSalaryBillToken", "ip");
rs.execute("select APPID from ECOLOGY_BIZ_EC where id =" + appidId);
// 获取appid
String appid ="";
if (rs.next() && StringUtils.isNotEmpty(rs.getString("APPID"))) {
appid = rs.getString("APPID");
} else {
return resultMap;
}
String sql= " SELECT conf_value FROM hrsa_salary_sys_conf t WHERE delete_type = 0 AND conf_key = 'SALARY_TOKEN_SECRET'";
rs.execute(sql);
String secret = "";
if (rs.next() && StringUtils.isNotBlank(rs.getString("conf_value"))) {
// 从数据库中拿secret
secret = rs.getString("conf_value");
} else {
sql= " update hrsa_salary_sys_conf set delete_type=1 WHERE delete_type = 0 AND conf_key in( 'SALARY_TOKEN_SECRET', 'SALARY_TOKEN_SPK')";
rs.execute(sql);
// 注册获取secret
// 获取当前异构系统RSA加密的公钥
String cpk = new RSA().getRSA_PUB();
//封装参数到请求头
heads.put("appid", appid);
heads.put("cpk", cpk);
// 调用ECOLOGY系统接口进行注册
String data = post(httpKey + ip + "/api/ec/dev/auth/regist", null, heads);
Map<String, Object> datas = JSONObject.parseObject(data, new TypeReference<Map<String, Object>>() {});
// ECOLOGY返回的系统公钥
String spk = (String) (datas.get("spk"));
RSA rsa = new RSA();
// 对秘钥进行加密传输,防止篡改数据
secret = rsa.encrypt(null, (String) (datas.get("secrit")), null, "utf-8", spk, false);
// secret存库
String date = SalaryDateUtil.getFormatLocalDateTime(LocalDateTime.now());
sql = String.format("insert into hrsa_salary_sys_conf(id, conf_key, conf_value, title, module, order_weight, delete_type, create_time, update_time) values (%s,'%s','%s','%s','%s',%s,%s,'%s','%s')",
IdGenerator.generate(), "SALARY_TOKEN_SECRET", secret, "token", "basic",0,0,date,date);
rs.execute(sql);
// 保存spk
sql = String.format("insert into hrsa_salary_sys_conf(id, conf_key, conf_value, title, module, order_weight, delete_type, create_time, update_time) values (%s,'%s','%s','%s','%s',%s,%s,'%s','%s')",
IdGenerator.generate(), "SALARY_TOKEN_SPK", spk, "spk", "basic",0,0,date,date);
rs.execute(sql);
}
//封装参数到请求头
heads.put("appid", appid);
heads.put("secret", secret);
//调用ECOLOGY系统接口进行注册
String data2 = post(httpKey + ip + "/api/ec/dev/auth/applytoken", null, heads);
// 通过第一步注册许可时返回spk公钥对userid进行加密生成的密文
sql= " SELECT conf_value FROM hrsa_salary_sys_conf t WHERE delete_type = 0 AND conf_key = 'SALARY_TOKEN_SPK'";
rs.execute(sql);
if (rs.next()){
String spk = rs.getString("conf_value");
// 对uid进行加密
RSA rsa = new RSA();
String encryptUid = rsa.encrypt(null, uid.toString(), null, "utf-8", spk, false);
String token = (String)JSONObject.parseObject(data2, new TypeReference<Map<String, Object>>() {}).get("token");
resultMap.put("userid", encryptUid);
resultMap.put("token", token);
resultMap.put("appid",appid);
return resultMap;
} else {
throw new SalaryRunTimeException("spk不存在");
}
}
/**
* 此方法仅供参考第三方系统可采用自己的方式调用http接口
*
* @param path 请求路径
* @param data 请求参数
* @return
*/
public static String post(String path, Map<String, String> params, Map<String, String> data) {
try {
String str = "";
// if (params != null) {
// StringBuilder stringBuilder = new StringBuilder("?");
// for (Map.Entry<String, String> entry : params.entrySet()) {
// stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
// }
// if (stringBuilder.length() > 1)
// path += stringBuilder.substring(0, stringBuilder.length() - 1);
// }
URL url = new URL(path);
//打开和url之间的连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// PrintWriter out = null;
// 请求参数 编码为 utf-8
//请求方式
conn.setRequestMethod("POST");
//设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
if (data != null) {
for (Map.Entry<String, String> entry : data.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
//设置是否向httpUrlConnection输出设置是否从httpUrlConnection读入此外发送post请求必须设置这两个
//最常用的Http请求无非是get和postget请求可以获取静态页面也可以把参数放在URL字串后面传递给servlet
//post与get的 不同之处在于post的参数不是放在URL字串里面而是放在http请求的正文内。
conn.setDoOutput(true);
conn.setDoInput(true);
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
if (params != null) {
out.write(mapToStr(params));
}
//缓冲数据
out.flush();
out.close();
//获取URLConnection对象对应的输入流
InputStream is = conn.getInputStream();
//构造一个字符流缓存
BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
String result = "";
while ((str = br.readLine()) != null) {
result = str;
}
//关闭流
is.close();
//断开连接最好写上disconnect是在底层tcp socket链接空闲时才切断。如果正在被其他线程使用就不切断。
//固定多线程的话如果不disconnect链接会增多直到收发不出信息。写上disconnect后正常一些。
conn.disconnect();
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将Map转换成字符串参数用于POST GET 请求
*
* @param map
* @return
*/
public static String mapToStr(Map<String, String> map) {
StringBuilder stringBuilder = new StringBuilder();
if (map != null) {
for (Map.Entry<String, String> entry : map.entrySet()) {
stringBuilder.append(entry.getKey());
if (entry.getValue() != null) {
stringBuilder.append("=").append(entry.getValue());
}
stringBuilder.append("&");
}
}
if (stringBuilder.length() > 0) {
return stringBuilder.substring(0, stringBuilder.length() - 1);
}
return null;
}
}